summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2012-09-29 17:36:27 -0400
committerRich Felker <dalias@aerifal.cx>2012-09-29 17:36:27 -0400
commit79a5e73e518213d5e77a06cfc0db74ffbf7922c6 (patch)
treea13e64b58de93ae8a94787414007c4db0d72843d /src
parent3d8d90c5ccf66f1d243cb1b248b047295c197b5c (diff)
downloadmusl-79a5e73e518213d5e77a06cfc0db74ffbf7922c6.tar.gz
musl-79a5e73e518213d5e77a06cfc0db74ffbf7922c6.tar.bz2
musl-79a5e73e518213d5e77a06cfc0db74ffbf7922c6.tar.xz
musl-79a5e73e518213d5e77a06cfc0db74ffbf7922c6.zip
emulate SOCK_CLOEXEC and SOCK_NONBLOCK for old (pre-2.6.27) kernels
also update syslog to use SOCK_CLOEXEC rather than separate fcntl step, to make it safe in multithreaded programs that run external programs. emulation is not atomic; it could be made atomic by holding a lock on forking during the operation, but this seems like overkill. my goal is not to achieve perfect behavior on old kernels (which have plenty of other imperfect behavior already) but to avoid catastrophic breakage in (1) syslog, which would give no output on old kernels with the change to use SOCK_CLOEXEC, and (2) programs built on a new kernel where configure scripts detected a working SOCK_CLOEXEC, which later get run on older kernels (they may otherwise fail to work completely).
Diffstat (limited to 'src')
-rw-r--r--src/misc/syslog.c3
-rw-r--r--src/network/socket.c15
2 files changed, 15 insertions, 3 deletions
diff --git a/src/misc/syslog.c b/src/misc/syslog.c
index a4f36dee..8de34f8d 100644
--- a/src/misc/syslog.c
+++ b/src/misc/syslog.c
@@ -51,8 +51,7 @@ static void __openlog(const char *ident, int opt, int facility)
if (!(opt & LOG_NDELAY) || log_fd>=0) return;
- log_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
- fcntl(log_fd, F_SETFD, FD_CLOEXEC);
+ log_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
}
void openlog(const char *ident, int opt, int facility)
diff --git a/src/network/socket.c b/src/network/socket.c
index 4f1e86db..ba8d45b1 100644
--- a/src/network/socket.c
+++ b/src/network/socket.c
@@ -1,7 +1,20 @@
#include <sys/socket.h>
+#include <fcntl.h>
+#include <errno.h>
#include "syscall.h"
int socket(int domain, int type, int protocol)
{
- return socketcall(socket, domain, type, protocol, 0, 0, 0);
+ int s = socketcall(socket, domain, type, protocol, 0, 0, 0);
+ if (s<0 && errno==EINVAL && (type&(SOCK_CLOEXEC|SOCK_NONBLOCK))) {
+ s = socketcall(socket, domain,
+ type & ~(SOCK_CLOEXEC|SOCK_NONBLOCK),
+ protocol, 0, 0, 0);
+ if (s < 0) return s;
+ if (type & SOCK_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+ if (type & SOCK_NONBLOCK)
+ fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
+ }
+ return s;
}