diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index 95a21378b..deac201c0 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -1044,6 +1044,7 @@ pipe SIGFE pipe2 SIGFE poll SIGFE popen SIGFE +posix_close SIGFE posix_fadvise SIGFE posix_fallocate SIGFE posix_getdents SIGFE diff --git a/winsup/cygwin/fhandler/base.cc b/winsup/cygwin/fhandler/base.cc index b889157d6..8f3dbd4ed 100644 --- a/winsup/cygwin/fhandler/base.cc +++ b/winsup/cygwin/fhandler/base.cc @@ -1255,7 +1255,7 @@ fhandler_base::pwrite (void *, size_t, off_t, void *) } int -fhandler_base::close_with_arch () +fhandler_base::close_with_arch (int flag) { int res; fhandler_base *fh; @@ -1285,7 +1285,7 @@ fhandler_base::close_with_arch () } cleanup (); - res = fh->close (); + res = fh->close (flag); if (archetype) { cygheap->fdtab.delete_archetype (archetype); @@ -1304,7 +1304,7 @@ fhandler_base::cleanup () } int -fhandler_base::close () +fhandler_base::close (int flag) { int res = -1; diff --git a/winsup/cygwin/fhandler/clipboard.cc b/winsup/cygwin/fhandler/clipboard.cc index 376d43440..12691c7c1 100644 --- a/winsup/cygwin/fhandler/clipboard.cc +++ b/winsup/cygwin/fhandler/clipboard.cc @@ -341,7 +341,7 @@ fhandler_dev_clipboard::lseek (off_t offset, int whence) } int -fhandler_dev_clipboard::close () +fhandler_dev_clipboard::close (int flag) { if (!have_execed) { diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index c6c261420..7aa09b0f5 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -1970,7 +1970,7 @@ fhandler_console::post_open_setup (int fd) } int -fhandler_console::close () +fhandler_console::close (int flag) { debug_printf ("closing: %p, %p", get_handle (), get_output_handle ()); diff --git a/winsup/cygwin/fhandler/dev.cc b/winsup/cygwin/fhandler/dev.cc index c6bda5654..8266397c3 100644 --- a/winsup/cygwin/fhandler/dev.cc +++ b/winsup/cygwin/fhandler/dev.cc @@ -59,7 +59,7 @@ fhandler_dev::open (int flags, mode_t mode) } int -fhandler_dev::close () +fhandler_dev::close (int flag) { return fhandler_disk_file::close (); } diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc index f41198ec0..d54d3747e 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -1654,7 +1654,7 @@ fhandler_disk_file::open (int flags, mode_t mode) } int -fhandler_disk_file::close () +fhandler_disk_file::close (int flag) { /* Close extra pread/pwrite handle, if it exists. */ if (prw_handle) diff --git a/winsup/cygwin/fhandler/dsp.cc b/winsup/cygwin/fhandler/dsp.cc index 605a048f3..13a9c75c3 100644 --- a/winsup/cygwin/fhandler/dsp.cc +++ b/winsup/cygwin/fhandler/dsp.cc @@ -1230,7 +1230,7 @@ fhandler_dev_dsp::close_audio_out (bool immediately) } int -fhandler_dev_dsp::close () +fhandler_dev_dsp::close (int flag) { debug_printf ("audio_in=%p audio_out=%p", audio_in_, audio_out_); being_closed = true; diff --git a/winsup/cygwin/fhandler/fifo.cc b/winsup/cygwin/fhandler/fifo.cc index 7a03894fa..15117db6e 100644 --- a/winsup/cygwin/fhandler/fifo.cc +++ b/winsup/cygwin/fhandler/fifo.cc @@ -1522,7 +1522,7 @@ fhandler_fifo::cancel_reader_thread () } int -fhandler_fifo::close () +fhandler_fifo::close (int flag) { isclosed (true); if (select_sem) diff --git a/winsup/cygwin/fhandler/floppy.cc b/winsup/cygwin/fhandler/floppy.cc index e883ab697..082a2736f 100644 --- a/winsup/cygwin/fhandler/floppy.cc +++ b/winsup/cygwin/fhandler/floppy.cc @@ -357,7 +357,7 @@ fhandler_dev_floppy::open (int flags, mode_t) } int -fhandler_dev_floppy::close () +fhandler_dev_floppy::close (int flag) { int ret = fhandler_dev_raw::close (); diff --git a/winsup/cygwin/fhandler/mqueue.cc b/winsup/cygwin/fhandler/mqueue.cc index 2bf2cb0ea..f2aeb56a9 100644 --- a/winsup/cygwin/fhandler/mqueue.cc +++ b/winsup/cygwin/fhandler/mqueue.cc @@ -559,7 +559,7 @@ fhandler_mqueue::ioctl (unsigned int cmd, void *buf) } int -fhandler_mqueue::close () +fhandler_mqueue::close (int flag) { __try { diff --git a/winsup/cygwin/fhandler/netdrive.cc b/winsup/cygwin/fhandler/netdrive.cc index 90e5a2217..f9412da2f 100644 --- a/winsup/cygwin/fhandler/netdrive.cc +++ b/winsup/cygwin/fhandler/netdrive.cc @@ -580,7 +580,7 @@ fhandler_netdrive::open (int flags, mode_t mode) } int -fhandler_netdrive::close () +fhandler_netdrive::close (int flag) { /* Skip fhandler_virtual::close, which is a no-op. */ return fhandler_base::close (); diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc index d76a4e74e..074cb50ca 100644 --- a/winsup/cygwin/fhandler/pipe.cc +++ b/winsup/cygwin/fhandler/pipe.cc @@ -759,7 +759,7 @@ fhandler_pipe::dup (fhandler_base *child, int flags) } int -fhandler_pipe::close () +fhandler_pipe::close (int flag) { isclosed (true); if (select_sem) diff --git a/winsup/cygwin/fhandler/procsys.cc b/winsup/cygwin/fhandler/procsys.cc index 4fa00481a..aa021e89c 100644 --- a/winsup/cygwin/fhandler/procsys.cc +++ b/winsup/cygwin/fhandler/procsys.cc @@ -472,7 +472,7 @@ fhandler_procsys::open (int flags, mode_t mode) } int -fhandler_procsys::close () +fhandler_procsys::close (int flag) { if (!nohandle ()) NtClose (get_handle ()); diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 4f0f71812..ac00a280b 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -981,7 +981,7 @@ fhandler_pty_slave::cleanup () } int -fhandler_pty_slave::close () +fhandler_pty_slave::close (int flag) { termios_printf ("closing last open %s handle", ttyname ()); if (inuse && !CloseHandle (inuse)) @@ -1957,7 +1957,7 @@ fhandler_pty_common::lseek (off_t, int) } int -fhandler_pty_common::close () +fhandler_pty_common::close (int flag) { termios_printf ("pty%d <%p,%p> closing", get_minor (), get_handle (), get_output_handle ()); @@ -2004,7 +2004,7 @@ fhandler_pty_master::cleanup () } int -fhandler_pty_master::close () +fhandler_pty_master::close (int flag) { OBJECT_BASIC_INFORMATION obi; NTSTATUS status; diff --git a/winsup/cygwin/fhandler/registry.cc b/winsup/cygwin/fhandler/registry.cc index ac413af9b..26ee05fe9 100644 --- a/winsup/cygwin/fhandler/registry.cc +++ b/winsup/cygwin/fhandler/registry.cc @@ -898,7 +898,7 @@ out: } int -fhandler_registry::close () +fhandler_registry::close (int flag) { int res = fhandler_virtual::close (); if (res != 0) diff --git a/winsup/cygwin/fhandler/socket_inet.cc b/winsup/cygwin/fhandler/socket_inet.cc index 63cc498f1..22dfed63d 100644 --- a/winsup/cygwin/fhandler/socket_inet.cc +++ b/winsup/cygwin/fhandler/socket_inet.cc @@ -1035,10 +1035,25 @@ fhandler_socket_wsock::shutdown (int how) } int -fhandler_socket_wsock::close () +fhandler_socket_wsock::close (int flag) { int res = 0; + unsigned wait_flags; + switch (flag) + { + /* See comment preceeding close() functions in syscalls.cc. Given + WSAEWOULDBLOCK leaves the socket open, the default behaviour is + equivalent to posix_close w/ POSIX_CLOSE_RESTART. */ + case -1: + case POSIX_CLOSE_RESTART: + wait_flags = cw_cancel | cw_sig; + break; + case 0: + default: /* shouldn't happen, already handled in syscall.cc:__close() */ + wait_flags = cw_cancel | cw_sig | cw_sig_restart; + break; + } release_events (); while ((res = ::closesocket (get_socket ())) != 0) { @@ -1048,7 +1063,7 @@ fhandler_socket_wsock::close () res = -1; break; } - if (cygwait (10) == WAIT_SIGNALED) + if (cygwait (NULL, 10, wait_flags) == WAIT_SIGNALED) { set_errno (EINTR); res = -1; diff --git a/winsup/cygwin/fhandler/socket_local.cc b/winsup/cygwin/fhandler/socket_local.cc index e4a88169b..270a1ef31 100644 --- a/winsup/cygwin/fhandler/socket_local.cc +++ b/winsup/cygwin/fhandler/socket_local.cc @@ -649,7 +649,7 @@ fhandler_socket_local::open (int flags, mode_t mode) } int -fhandler_socket_local::close () +fhandler_socket_local::close (int flag) { if (get_flags () & O_PATH) return fhandler_base::close (); diff --git a/winsup/cygwin/fhandler/socket_unix.cc b/winsup/cygwin/fhandler/socket_unix.cc index 0cd97f625..aacaa5c62 100644 --- a/winsup/cygwin/fhandler/socket_unix.cc +++ b/winsup/cygwin/fhandler/socket_unix.cc @@ -1795,7 +1795,7 @@ fhandler_socket_unix::open (int flags, mode_t mode) } int -fhandler_socket_unix::close () +fhandler_socket_unix::close (int flag) { if (get_flags () & O_PATH) return fhandler_base::close (); diff --git a/winsup/cygwin/fhandler/tape.cc b/winsup/cygwin/fhandler/tape.cc index 732fd1bb7..deed4e3d6 100644 --- a/winsup/cygwin/fhandler/tape.cc +++ b/winsup/cygwin/fhandler/tape.cc @@ -1249,7 +1249,7 @@ fhandler_dev_tape::open (int flags, mode_t) } int -fhandler_dev_tape::close () +fhandler_dev_tape::close (int flag) { int ret = 0; int cret = 0; diff --git a/winsup/cygwin/fhandler/timerfd.cc b/winsup/cygwin/fhandler/timerfd.cc index 9269494db..982950d00 100644 --- a/winsup/cygwin/fhandler/timerfd.cc +++ b/winsup/cygwin/fhandler/timerfd.cc @@ -241,7 +241,7 @@ fhandler_timerfd::fixup_after_exec () } int -fhandler_timerfd::close () +fhandler_timerfd::close (int flag) { int ret = -1; diff --git a/winsup/cygwin/fhandler/virtual.cc b/winsup/cygwin/fhandler/virtual.cc index 90653fbf9..4a7b2b725 100644 --- a/winsup/cygwin/fhandler/virtual.cc +++ b/winsup/cygwin/fhandler/virtual.cc @@ -162,7 +162,7 @@ fhandler_virtual::dup (fhandler_base * child, int flags) } int -fhandler_virtual::close () +fhandler_virtual::close (int flag) { if (!have_execed) { diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 4dc3e0fcf..02280746d 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -492,12 +492,13 @@ details. */ 355: Implement setproctitle. 356: Export posix_spawn_file_actions_addchdir and posix_spawn_file_actions_addfchdir. + 357: Export posix_close. Note that we forgot to bump the api for ualarm, strtoll, strtoull, sigaltstack, sethostname. */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 356 +#define CYGWIN_VERSION_API_MINOR 357 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible changes are made to the shared diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 3550481b5..273ee31e1 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -364,8 +364,8 @@ class fhandler_base void set_unique_id (int64_t u) { unique_id = u; } void set_unique_id () { NtAllocateLocallyUniqueId ((PLUID) &unique_id); } - int close_with_arch (); - virtual int close (); + int close_with_arch (int flag = -1); + virtual int close (int flag = -1); virtual void cleanup (); int _archetype_usecount (const char *fn, int ln, int n) { @@ -602,7 +602,7 @@ class fhandler_socket: public fhandler_base virtual int getsockname (struct sockaddr *name, int *namelen) = 0; virtual int getpeername (struct sockaddr *name, int *namelen) = 0; virtual int shutdown (int how) = 0; - virtual int close () = 0; + virtual int close (int flag = -1) = 0; virtual int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); virtual ssize_t recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen) = 0; @@ -731,7 +731,7 @@ class fhandler_socket_wsock: public fhandler_socket ssize_t write (const void *ptr, size_t len); ssize_t writev (const struct iovec *, int iovcnt, ssize_t tot = -1); int shutdown (int how); - int close (); + int close (int flag = -1); int ioctl (unsigned int cmd, void *); int fcntl (int cmd, intptr_t); @@ -869,7 +869,7 @@ class fhandler_socket_local: public fhandler_socket_wsock __socklen_t *optlen); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); int fcntl (int cmd, intptr_t); int fstat (struct stat *buf); int fstatvfs (struct statvfs *buf); @@ -1132,7 +1132,7 @@ class fhandler_socket_unix : public fhandler_socket int getpeername (struct sockaddr *name, int *namelen); int shutdown (int how); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); int getpeereid (pid_t *pid, uid_t *euid, gid_t *egid); ssize_t recvmsg (struct msghdr *msg, int flags); ssize_t recvfrom (void *ptr, size_t len, int flags, @@ -1237,7 +1237,7 @@ public: void fixup_after_fork (HANDLE); int dup (fhandler_base *child, int); void set_close_on_exec (bool val); - int close (); + int close (int flag = -1); void raw_read (void *ptr, size_t& len); int ioctl (unsigned int cmd, void *); int fstat (struct stat *buf); @@ -1286,7 +1286,7 @@ struct fifo_client_handler fifo_client_connect_state _state; bool last_read; /* true if our last successful read was from this client. */ fifo_client_handler () : h (NULL), _state (fc_unknown), last_read (false) {} - void close () { NtClose (h); } + void close (int flag = -1) { NtClose (h); } fifo_client_connect_state get_state () const { return _state; } void set_state (fifo_client_connect_state s) { _state = s; } /* Query O/S. Return previous state. */ @@ -1496,7 +1496,7 @@ public: int open (int, mode_t); off_t lseek (off_t offset, int whence); - int close (); + int close (int flag = -1); int fcntl (int cmd, intptr_t); int dup (fhandler_base *child, int); bool isfifo () const { return true; } @@ -1614,7 +1614,7 @@ class fhandler_dev_floppy: public fhandler_dev_raw fhandler_dev_floppy (); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); int dup (fhandler_base *child, int); void raw_read (void *ptr, size_t& ulen); ssize_t raw_write (const void *ptr, size_t ulen); @@ -1655,7 +1655,7 @@ class fhandler_dev_tape: public fhandler_dev_raw fhandler_dev_tape (); int open (int flags, mode_t mode = 0); - virtual int close (); + virtual int close (int flag = -1); void raw_read (void *ptr, size_t& ulen); ssize_t raw_write (const void *ptr, size_t ulen); @@ -1708,7 +1708,7 @@ class fhandler_disk_file: public fhandler_base fhandler_disk_file (path_conv &pc); int open (int flags, mode_t mode); - int close (); + int close (int flag = -1); int fcntl (int cmd, intptr_t); int dup (fhandler_base *child, int); void fixup_after_fork (HANDLE parent); @@ -1772,7 +1772,7 @@ class fhandler_dev: public fhandler_disk_file public: fhandler_dev (); int open (int flags, mode_t mode); - int close (); + int close (int flag = -1); int fstat (struct stat *buf); int fstatvfs (struct statvfs *buf); int rmdir (); @@ -2259,7 +2259,7 @@ private: void read (void *ptr, size_t& len); ssize_t write (const void *ptr, size_t len); void doecho (const void *str, DWORD len); - int close (); + int close (int flag = -1); static bool exists () { acquire_attach_mutex (mutex_timeout); @@ -2388,7 +2388,7 @@ class fhandler_pty_common: public fhandler_termios DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms); void __release_output_mutex (const char *fn, int ln); - int close (); + int close (int flag = -1); off_t lseek (off_t, int); bool bytes_available (DWORD& n); void set_close_on_exec (bool val); @@ -2459,7 +2459,7 @@ class fhandler_pty_slave: public fhandler_pty_common int tcgetattr (struct termios *t); int tcflush (int); int ioctl (unsigned int cmd, void *); - int close (); + int close (int flag = -1); void cleanup (); int dup (fhandler_base *child, int); void fixup_after_fork (HANDLE parent); @@ -2568,7 +2568,7 @@ public: bool open_setup (int flags); ssize_t write (const void *ptr, size_t len); void read (void *ptr, size_t& len); - int close (); + int close (int flag = -1); void cleanup (); int tcsetattr (int a, const struct termios *t); @@ -2729,7 +2729,7 @@ class fhandler_dev_clipboard: public fhandler_base ssize_t write (const void *ptr, size_t len); void read (void *ptr, size_t& len); off_t lseek (off_t offset, int whence); - int close (); + int close (int flag = -1); int dup (fhandler_base *child, int); void fixup_after_exec (); @@ -2766,7 +2766,7 @@ class fhandler_windows: public fhandler_base void read (void *ptr, size_t& len); int ioctl (unsigned int cmd, void *); off_t lseek (off_t, int) { return 0; } - int close () { return 0; } + int close (int flag = -1) { return 0; } select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); @@ -2845,7 +2845,7 @@ class fhandler_dev_dsp: public fhandler_base void read (void *, size_t&); int ioctl (unsigned int, void *); int fcntl (int cmd, intptr_t); - int close (); + int close (int flag = -1); void fixup_after_fork (HANDLE); void fixup_after_exec (); bool open_setup (int); @@ -2918,7 +2918,7 @@ class fhandler_virtual : public fhandler_base off_t lseek (off_t, int); int dup (fhandler_base *child, int); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); int fstatvfs (struct statvfs *buf); int fchmod (mode_t mode); int fchown (uid_t uid, gid_t gid); @@ -2991,7 +2991,7 @@ class fhandler_procsys: public fhandler_virtual void seekdir (DIR *, long); int closedir (DIR *); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); void read (void *ptr, size_t& len); ssize_t write (const void *ptr, size_t len); int fstat (struct stat *buf); @@ -3055,7 +3055,7 @@ class fhandler_netdrive: public fhandler_virtual void rewinddir (DIR *); int closedir (DIR *); int open (int flags, mode_t mode = 0); - int close (); + int close (int flag = -1); int fstat (struct stat *buf); fhandler_netdrive (void *) {} @@ -3096,7 +3096,7 @@ class fhandler_registry: public fhandler_proc int open (int flags, mode_t mode = 0); int fstat (struct stat *buf); bool fill_filebuf (); - int close (); + int close (int flag = -1); int dup (fhandler_base *child, int); fhandler_registry (void *) {} @@ -3348,7 +3348,7 @@ class fhandler_timerfd : public fhandler_base ssize_t write (const void *, size_t); int dup (fhandler_base *child, int); int ioctl (unsigned int, void *); - int close (); + int close (int flag = -1); HANDLE get_timerfd_handle (); @@ -3441,7 +3441,7 @@ public: int dup (fhandler_base *, int); int fcntl (int cmd, intptr_t); int ioctl (unsigned int, void *); - int close (); + int close (int flag = -1); void copy_from (fhandler_base *x) { diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 4890131b7..c93bf4c95 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1678,13 +1678,27 @@ lseek (int fd, off_t pos, int dir) return res; } -extern "C" int -close (int fd) +/* Takes three flag values: + + -1: default behaviour, called from close(2). + + 0: called via posix_close (0), i.e., the call shall not return -1 with + errno set to [EINTR], which implies that fildes will always be closed + (except for [EBADF], where fildes was invalid). + + POSIX_CLOSE_RESTART: called via posix_close (POSIX_CLOSE_RESTART), i. e. + if the call is interrupted by a signal that is to be caught, the call + may return -1 with errno set to [EINTR], in which case fildes + shall be left open; however, it is unspecified whether fildes can + subsequently be passed to any function except close() or posix_close() + without error. + + Note that POSIX_CLOSE_RESTART means the opposite of SA_RESTART! */ +static inline int +__close (int fd, int flag) { int res; - syscall_printf ("close(%d)", fd); - pthread_testcancel (); cygheap_fdget cfd (fd, true); @@ -1692,14 +1706,44 @@ close (int fd) res = -1; else { - res = cfd->close_with_arch (); - cfd.release (); + res = cfd->close_with_arch (flag); + if (res != EINTR) + cfd.release (); } - syscall_printf ("%R = close(%d)", res, fd); return res; } +extern "C" int +close (int fd) +{ + syscall_printf ("close(%d)", fd); + int ret = __close (fd, -1); + syscall_printf ("%R = close(%d)", ret, fd); + return ret; +} + +extern "C" int +posix_close (int fd, int flag) +{ + int real_flag = flag; + + /* POSIX-1.2024 says: If flag is invalid, posix_close() may fail with errno + set to [EINVAL], but shall otherwise behave as if flag had been 0 and + close fd. */ + if (real_flag != 0 && real_flag != POSIX_CLOSE_RESTART) + real_flag = 0; + syscall_printf ("posix_close(%d, %d)", fd, flag); + int ret = __close (fd, real_flag); + if (!ret && flag != real_flag) + { + set_errno (EINVAL); + ret = -1; + } + syscall_printf ("%R = posix_close(%d, %d)", ret, fd, flag); + return ret; +} + extern "C" int isatty (int fd) {