diff options
author | jilles <jilles@FreeBSD.org> | 2013-05-01 20:10:21 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2013-05-01 20:10:21 +0000 |
commit | 299afd25fd6dead39bf5c78572782db885579911 (patch) | |
tree | c530c7ecc418cacfa14b49c004393242e6613d6b /lib/libthr/thread | |
parent | 19e5409088a95e1f704e9a1b2e7737b3e76608e9 (diff) | |
download | FreeBSD-src-299afd25fd6dead39bf5c78572782db885579911.zip FreeBSD-src-299afd25fd6dead39bf5c78572782db885579911.tar.gz |
Add accept4() system call.
The accept4() function, compared to accept(), allows setting the new file
descriptor atomically close-on-exec and explicitly controlling the
non-blocking status on the new socket. (Note that the latter point means
that accept() is not equivalent to any form of accept4().)
The linuxulator's accept4 implementation leaves a race window where the new
file descriptor is not close-on-exec because it calls sys_accept(). This
implementation leaves no such race window (by using falloc() flags). The
linuxulator could be fixed and simplified by using the new code.
Like accept(), accept4() is async-signal-safe, a cancellation point and
permitted in capability mode.
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r-- | lib/libthr/thread/thr_syscalls.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 2327d74..7a08302 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -101,6 +101,7 @@ extern pid_t __waitpid(pid_t, int *, int); extern int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *); extern int __sys_accept(int, struct sockaddr *, socklen_t *); +extern int __sys_accept4(int, struct sockaddr *, socklen_t *, int); extern int __sys_connect(int, const struct sockaddr *, socklen_t); extern int __sys_fsync(int); extern int __sys_msync(void *, size_t, int); @@ -129,6 +130,7 @@ int ___usleep(useconds_t useconds); pid_t ___wait(int *); pid_t ___waitpid(pid_t, int *, int); int __accept(int, struct sockaddr *, socklen_t *); +int __accept4(int, struct sockaddr *, socklen_t *, int); int __aio_suspend(const struct aiocb * const iocbs[], int, const struct timespec *); int __close(int); @@ -176,6 +178,26 @@ __accept(int s, struct sockaddr *addr, socklen_t *addrlen) return (ret); } +__weak_reference(__accept4, accept4); + +/* + * Cancellation behavior: + * If thread is canceled, no socket is created. + */ +int +__accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) +{ + struct pthread *curthread; + int ret; + + curthread = _get_curthread(); + _thr_cancel_enter(curthread); + ret = __sys_accept4(s, addr, addrlen, flags); + _thr_cancel_leave(curthread, ret == -1); + + return (ret); +} + __weak_reference(__aio_suspend, aio_suspend); int |