4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-03-03 05:25:24 +08:00

Cygwin: implement posix_close

per
https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_close.html

Add a flag value to fhandler_*::close() and close_with_arch() methods,
taking -1 as default argument, used to indicate default close(2)
behaviour.

The only fhandlers capable of returning EINTR are the INET based
socket fhandlers.  Handle -1 and POSIX_CLOSE_RESTART equivalent,
making close() and posix_close(POSIX_CLOSE_RESTART) behaving
identically.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2025-01-28 16:50:12 +01:00
parent c7eb1a1f52
commit d52d983e5b
24 changed files with 120 additions and 59 deletions

@ -1044,6 +1044,7 @@ pipe SIGFE
pipe2 SIGFE
poll SIGFE
popen SIGFE
posix_close SIGFE
posix_fadvise SIGFE
posix_fallocate SIGFE
posix_getdents SIGFE

@ -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;

@ -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)
{

@ -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 ());

@ -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 ();
}

@ -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)

@ -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;

@ -1522,7 +1522,7 @@ fhandler_fifo::cancel_reader_thread ()
}
int
fhandler_fifo::close ()
fhandler_fifo::close (int flag)
{
isclosed (true);
if (select_sem)

@ -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 ();

@ -559,7 +559,7 @@ fhandler_mqueue::ioctl (unsigned int cmd, void *buf)
}
int
fhandler_mqueue::close ()
fhandler_mqueue::close (int flag)
{
__try
{

@ -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 ();

@ -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)

@ -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 ());

@ -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;

@ -898,7 +898,7 @@ out:
}
int
fhandler_registry::close ()
fhandler_registry::close (int flag)
{
int res = fhandler_virtual::close ();
if (res != 0)

@ -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;

@ -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 ();

@ -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 ();

@ -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;

@ -241,7 +241,7 @@ fhandler_timerfd::fixup_after_exec ()
}
int
fhandler_timerfd::close ()
fhandler_timerfd::close (int flag)
{
int ret = -1;

@ -162,7 +162,7 @@ fhandler_virtual::dup (fhandler_base * child, int flags)
}
int
fhandler_virtual::close ()
fhandler_virtual::close (int flag)
{
if (!have_execed)
{

@ -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

@ -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)
{

@ -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)
{