Index: configure.ac ================================================================== --- configure.ac +++ configure.ac @@ -735,10 +735,12 @@ AC_CHECK_HEADERS(netinet/in.h, [ AC_DEFINE(OF_HAVE_NETINET_IN_H, 1, [Whether we have netinet/in.h]) ]) AC_CHECK_HEADERS([arpa/inet.h netdb.h]) + + AC_CHECK_FUNCS([paccept accept4]) AC_CHECK_FUNC(kqueue, [ AC_DEFINE(HAVE_KQUEUE, 1, [Whether we have kqueue]) AC_SUBST(OFKERNELEVENTOBSERVER_KQUEUE_M, "OFKernelEventObserver_kqueue.m") Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -91,10 +91,13 @@ #endif #ifndef O_BINARY # define O_BINARY 0 #endif +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 +#endif #ifndef O_EXLOCK # define O_EXLOCK 0 #endif #ifndef S_IRGRP @@ -888,10 +891,12 @@ @try { int flags; if ((flags = parseMode([mode UTF8String])) == -1) @throw [OFInvalidArgumentException exception]; + + flags |= O_CLOEXEC; #ifndef _WIN32 if ((_fd = open([path cStringWithEncoding: [OFSystemInfo native8BitEncoding]], flags, DEFAULT_MODE)) == -1) #else Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -288,14 +288,23 @@ results = of_resolve_host(host, port, SOCK_STREAM); for (iter = results; *iter != NULL; iter++) { of_resolver_result_t *result = *iter; +#if SOCK_CLOEXEC == 0 + int flags; +#endif - if ((_socket = socket(result->family, result->type, + if ((_socket = socket(result->family, + result->type | SOCK_CLOEXEC, result->protocol)) == INVALID_SOCKET) continue; + +#if SOCK_CLOEXEC == 0 + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif if (connect(_socket, result->address, result->addressLength) == -1) { close(_socket); _socket = INVALID_SOCKET; @@ -383,15 +392,25 @@ port = freePort--; #endif results = of_resolve_host(host, port, SOCK_STREAM); @try { - if ((_socket = socket(results[0]->family, results[0]->type, +#if SOCK_CLOEXEC == 0 + int flags; +#endif + + if ((_socket = socket(results[0]->family, + results[0]->type | SOCK_CLOEXEC, results[0]->protocol)) == INVALID_SOCKET) @throw [OFBindFailedException exceptionWithHost: host port: port socket: self]; + +#if SOCK_CLOEXEC == 0 + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, (socklen_t)sizeof(one))) @throw [OFSetOptionFailedException exceptionWithStream: self]; @@ -454,18 +473,34 @@ } - (instancetype)accept { OFTCPSocket *client = [[[[self class] alloc] init] autorelease]; +#if (!defined(HAVE_PACCEPT) && !defined(HAVE_ACCEPT4)) || !defined(SOCK_CLOEXEC) + int flags; +#endif client->_address = [client allocMemoryWithSize: sizeof(struct sockaddr_storage)]; client->_addressLength = (socklen_t)sizeof(struct sockaddr_storage); +#if defined(HAVE_PACCEPT) && defined(SOCK_CLOEXEC) + if ((client->_socket = paccept(_socket, client->_address, + &client->_addressLength, NULL, SOCK_CLOEXEC)) == INVALID_SOCKET) + @throw [OFAcceptFailedException exceptionWithSocket: self]; +#elif defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) + if ((client->_socket = accept4(_socket, client->_address, + &client->_addressLength, SOCK_CLOEXEC)) == INVALID_SOCKET) + @throw [OFAcceptFailedException exceptionWithSocket: self]; +#else if ((client->_socket = accept(_socket, client->_address, &client->_addressLength)) == INVALID_SOCKET) @throw [OFAcceptFailedException exceptionWithSocket: self]; + + if ((flags = fcntl(client->_socket, F_GETFD, 0)) != -1) + fcntl(client->_socket, F_SETFD, flags | FD_CLOEXEC); +#endif assert(client->_addressLength <= sizeof(struct sockaddr_storage)); if (client->_addressLength != sizeof(struct sockaddr_storage)) { @try { Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -393,15 +393,25 @@ port = freePort--; #endif results = of_resolve_host(host, port, SOCK_DGRAM); @try { - if ((_socket = socket(results[0]->family, results[0]->type, +#if SOCK_CLOEXEC == 0 + int flags; +#endif + + if ((_socket = socket(results[0]->family, + results[0]->type | SOCK_CLOEXEC, results[0]->protocol)) == INVALID_SOCKET) @throw [OFBindFailedException exceptionWithHost: host port: port socket: self]; + +#if SOCK_CLOEXEC == 0 + if ((flags = fcntl(_socket, F_GETFD, 0)) != -1) + fcntl(_socket, F_SETFD, flags | FD_CLOEXEC); +#endif if (bind(_socket, results[0]->address, results[0]->addressLength) == -1) { close(_socket); _socket = INVALID_SOCKET; Index: src/socket.h ================================================================== --- src/socket.h +++ src/socket.h @@ -19,10 +19,12 @@ #ifndef OF_HAVE_SOCKETS # error No sockets available! #endif #include + +#include #ifdef OF_HAVE_SYS_SOCKET_H # include #endif #ifdef OF_HAVE_NETINET_IN_H Index: src/socket_helpers.h ================================================================== --- src/socket_helpers.h +++ src/socket_helpers.h @@ -46,10 +46,14 @@ #endif #ifndef SOMAXCONN # define SOMAXCONN 32 #endif + +#ifndef SOCK_CLOEXEC +# define SOCK_CLOEXEC 0 +#endif #ifdef _WIN32 # define close(sock) closesocket(sock) #endif