phunix/minix/lib/libsys/closenb.c
David van Moolenbroek 491d647a3b VFS: support for suspending close(2) for sockets
This change effectively adds the VFS side of support for the SO_LINGER
socket option, by allowing file descriptor close operations to be
suspended (and later resumed) by socket drivers.  Currently, support
is limited to the close(2) system call--in all other cases where file
descriptors are closed (dup2, close-on-exec, process exit..), the
close operation still completes instantly.  As a general policy, the
close(2) return value will always indicate that the file descriptor
has been closed: either 0, or -1 with errno set to EINPROGRESS.  The
latter error may be thrown only when a suspended close is interrupted
by a signal.

As necessary for UDS, this change also introduces a closenb(2) system
call extension, allowing the caller to bypass blocking SO_LINGER close
behavior.  This extension allows UDS to avoid blocking on closing the
last reference to an in-flight file descriptor, in an atomic fashion.
The extension is currently part of libsys, but there is no reason why
userland would not be allowed to make this call, so it is deliberately
not protected from use by userland.

Change-Id: Iec77d6665232110346180017fc1300b1614910b7
2017-03-09 23:39:50 +00:00

28 lines
838 B
C

#include "syslib.h"
#include <string.h>
/*
* Non-blocking variant of close(2). This call is to be used by system
* services that need to close arbitrary local file descriptors. The purpose
* of the call is to avoid that such services end up blocking on closing socket
* file descriptors with the SO_LINGER socket option enabled. They cannot put
* the file pointer in non-blocking mode to that end, because the file pointer
* may be shared with other processes.
*
* Even though this call is defined for system services only, there is no harm
* in letting arbitrary user processes use this functionality. Thus, it needs
* no separate VFS call number.
*/
int
closenb(int fd)
{
message m;
memset(&m, 0, sizeof(m));
m.m_lc_vfs_close.fd = fd;
m.m_lc_vfs_close.nblock = 1;
return _taskcall(VFS_PROC_NR, VFS_CLOSE, &m);
}