Merge remote-tracking branch 'public/bug5112'

This commit is contained in:
Nick Mathewson 2012-04-24 11:14:22 -04:00
commit 6f5a74002a
2 changed files with 94 additions and 44 deletions

5
changes/bug5112 Normal file
View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- When Tor is built with kernel headers from a recent (last few
years) Linux kernel, do not fail to run on older (pre-2.6.28
Linux kernels). Fixes bug 5112; bugfix on 0.2.3.1-alpha.

View File

@ -123,16 +123,24 @@
int int
tor_open_cloexec(const char *path, int flags, unsigned mode) tor_open_cloexec(const char *path, int flags, unsigned mode)
{ {
int fd;
#ifdef O_CLOEXEC #ifdef O_CLOEXEC
return open(path, flags|O_CLOEXEC, mode); fd = open(path, flags|O_CLOEXEC, mode);
#else if (fd >= 0)
int fd = open(path, flags, mode); return fd;
/* If we got an error, see if it is EINVAL. EINVAL might indicate that,
* event though we were built on a system with O_CLOEXEC support, we
* are running on one without. */
if (errno != EINVAL)
return -1;
#endif
fd = open(path, flags, mode);
#ifdef FD_CLOEXEC #ifdef FD_CLOEXEC
if (fd >= 0) if (fd >= 0)
fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFD, FD_CLOEXEC);
#endif #endif
return fd; return fd;
#endif
} }
/** DOCDOC */ /** DOCDOC */
@ -968,19 +976,31 @@ tor_open_socket(int domain, int type, int protocol)
{ {
tor_socket_t s; tor_socket_t s;
#ifdef SOCK_CLOEXEC #ifdef SOCK_CLOEXEC
#define LINUX_CLOEXEC_OPEN_SOCKET s = socket(domain, type|SOCK_CLOEXEC, protocol);
type |= SOCK_CLOEXEC; if (SOCKET_OK(s))
#endif goto socket_ok;
/* If we got an error, see if it is EINVAL. EINVAL might indicate that,
* event though we were built on a system with SOCK_CLOEXEC support, we
* are running on one without. */
if (errno != EINVAL)
return s;
#endif /* SOCK_CLOEXEC */
s = socket(domain, type, protocol); s = socket(domain, type, protocol);
if (SOCKET_OK(s)) { if (! SOCKET_OK(s))
#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC) return s;
#if defined(FD_CLOEXEC)
fcntl(s, F_SETFD, FD_CLOEXEC); fcntl(s, F_SETFD, FD_CLOEXEC);
#endif #endif
goto socket_ok; /* So that socket_ok will not be unused. */
socket_ok:
socket_accounting_lock(); socket_accounting_lock();
++n_sockets_open; ++n_sockets_open;
mark_socket_open(s); mark_socket_open(s);
socket_accounting_unlock(); socket_accounting_unlock();
}
return s; return s;
} }
@ -990,20 +1010,31 @@ tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
{ {
tor_socket_t s; tor_socket_t s;
#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) #if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
#define LINUX_CLOEXEC_ACCEPT
s = accept4(sockfd, addr, len, SOCK_CLOEXEC); s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
#else if (SOCKET_OK(s))
s = accept(sockfd, addr, len); goto socket_ok;
/* If we got an error, see if it is EINVAL. EINVAL might indicate that,
* event though we were built on a system with accept4 support, we
* are running on one without. */
if (errno != EINVAL)
return s;
#endif #endif
if (SOCKET_OK(s)) {
#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC) s = accept(sockfd, addr, len);
if (!SOCKET_OK(s))
return s;
#if defined(FD_CLOEXEC)
fcntl(s, F_SETFD, FD_CLOEXEC); fcntl(s, F_SETFD, FD_CLOEXEC);
#endif #endif
goto socket_ok; /* So that socket_ok will not be unused. */
socket_ok:
socket_accounting_lock(); socket_accounting_lock();
++n_sockets_open; ++n_sockets_open;
mark_socket_open(s); mark_socket_open(s);
socket_accounting_unlock(); socket_accounting_unlock();
}
return s; return s;
} }
@ -1054,17 +1085,31 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
//don't use win32 socketpairs (they are always bad) //don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32) #if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
int r; int r;
#ifdef SOCK_CLOEXEC #ifdef SOCK_CLOEXEC
type |= SOCK_CLOEXEC; r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
if (r == 0)
goto sockets_ok;
/* If we got an error, see if it is EINVAL. EINVAL might indicate that,
* event though we were built on a system with SOCK_CLOEXEC support, we
* are running on one without. */
if (errno != EINVAL)
return -errno;
#endif #endif
r = socketpair(family, type, protocol, fd); r = socketpair(family, type, protocol, fd);
if (r == 0) { if (r < 0)
#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) return -errno;
#if defined(FD_CLOEXEC)
if (SOCKET_OK(fd[0])) if (SOCKET_OK(fd[0]))
fcntl(fd[0], F_SETFD, FD_CLOEXEC); fcntl(fd[0], F_SETFD, FD_CLOEXEC);
if (SOCKET_OK(fd[1])) if (SOCKET_OK(fd[1]))
fcntl(fd[1], F_SETFD, FD_CLOEXEC); fcntl(fd[1], F_SETFD, FD_CLOEXEC);
#endif #endif
goto sockets_ok; /* So that sockets_ok will not be unused. */
sockets_ok:
socket_accounting_lock(); socket_accounting_lock();
if (SOCKET_OK(fd[0])) { if (SOCKET_OK(fd[0])) {
++n_sockets_open; ++n_sockets_open;
@ -1075,8 +1120,8 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
mark_socket_open(fd[1]); mark_socket_open(fd[1]);
} }
socket_accounting_unlock(); socket_accounting_unlock();
}
return r < 0 ? -errno : r; return 0;
#else #else
/* This socketpair does not work when localhost is down. So /* This socketpair does not work when localhost is down. So
* it's really not the same thing at all. But it's close enough * it's really not the same thing at all. But it's close enough