|  | @@ -676,6 +676,23 @@ static int max_socket = -1;
 | 
	
		
			
				|  |  |   * eventdns and libevent.) */
 | 
	
		
			
				|  |  |  static int n_sockets_open = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/** Mutex to protect open_sockets, max_socket, and n_sockets_open. */
 | 
	
		
			
				|  |  | +static tor_mutex_t *socket_accounting_mutex = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static INLINE void
 | 
	
		
			
				|  |  | +socket_accounting_lock(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  if (PREDICT_UNLIKELY(!socket_accounting_mutex))
 | 
	
		
			
				|  |  | +    socket_accounting_mutex = tor_mutex_new();
 | 
	
		
			
				|  |  | +  tor_mutex_acquire(socket_accounting_mutex);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +static INLINE void
 | 
	
		
			
				|  |  | +socket_accounting_unlock(void)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  tor_mutex_release(socket_accounting_mutex);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /** As close(), but guaranteed to work for sockets across platforms (including
 | 
	
		
			
				|  |  |   * Windows, where close()ing a socket doesn't work.  Returns 0 on success, -1
 | 
	
		
			
				|  |  |   * on failure. */
 | 
	
	
		
			
				|  | @@ -683,15 +700,7 @@ int
 | 
	
		
			
				|  |  |  tor_close_socket(int s)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    int r = 0;
 | 
	
		
			
				|  |  | -#ifdef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | -  if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
 | 
	
		
			
				|  |  | -    log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
 | 
	
		
			
				|  |  | -             "socket(), or that was already closed or something.", s);
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    tor_assert(open_sockets && s <= max_socket);
 | 
	
		
			
				|  |  | -    bitarray_clear(open_sockets, s);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    /* On Windows, you have to call close() on fds returned by open(),
 | 
	
		
			
				|  |  |     * and closesocket() on fds returned by socket().  On Unix, everything
 | 
	
		
			
				|  |  |     * gets close()'d.  We abstract this difference by always using
 | 
	
	
		
			
				|  | @@ -703,6 +712,17 @@ tor_close_socket(int s)
 | 
	
		
			
				|  |  |  #else
 | 
	
		
			
				|  |  |    r = close(s);
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  socket_accounting_lock();
 | 
	
		
			
				|  |  | +#ifdef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | +  if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
 | 
	
		
			
				|  |  | +    log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
 | 
	
		
			
				|  |  | +             "socket(), or that was already closed or something.", s);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    tor_assert(open_sockets && s <= max_socket);
 | 
	
		
			
				|  |  | +    bitarray_clear(open_sockets, s);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  |    if (r == 0) {
 | 
	
		
			
				|  |  |      --n_sockets_open;
 | 
	
		
			
				|  |  |    } else {
 | 
	
	
		
			
				|  | @@ -717,9 +737,11 @@ tor_close_socket(int s)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |      r = -1;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    if (n_sockets_open < 0)
 | 
	
		
			
				|  |  |      log_warn(LD_BUG, "Our socket count is below zero: %d. Please submit a "
 | 
	
		
			
				|  |  |               "bug report.", n_sockets_open);
 | 
	
		
			
				|  |  | +  socket_accounting_unlock();
 | 
	
		
			
				|  |  |    return r;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -754,8 +776,10 @@ tor_open_socket(int domain, int type, int protocol)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    int s = socket(domain, type, protocol);
 | 
	
		
			
				|  |  |    if (s >= 0) {
 | 
	
		
			
				|  |  | +    socket_accounting_lock();
 | 
	
		
			
				|  |  |      ++n_sockets_open;
 | 
	
		
			
				|  |  |      mark_socket_open(s);
 | 
	
		
			
				|  |  | +    socket_accounting_unlock();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return s;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -766,8 +790,10 @@ tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |    int s = accept(sockfd, addr, len);
 | 
	
		
			
				|  |  |    if (s >= 0) {
 | 
	
		
			
				|  |  | +    socket_accounting_lock();
 | 
	
		
			
				|  |  |      ++n_sockets_open;
 | 
	
		
			
				|  |  |      mark_socket_open(s);
 | 
	
		
			
				|  |  | +    socket_accounting_unlock();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return s;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -776,7 +802,11 @@ tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
 | 
	
		
			
				|  |  |  int
 | 
	
		
			
				|  |  |  get_n_open_sockets(void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | -  return n_sockets_open;
 | 
	
		
			
				|  |  | +  int n;
 | 
	
		
			
				|  |  | +  socket_accounting_lock();
 | 
	
		
			
				|  |  | +  n = n_sockets_open;
 | 
	
		
			
				|  |  | +  socket_accounting_unlock();
 | 
	
		
			
				|  |  | +  return n;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Turn <b>socket</b> into a nonblocking socket.
 | 
	
	
		
			
				|  | @@ -817,6 +847,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
 | 
	
		
			
				|  |  |    int r;
 | 
	
		
			
				|  |  |    r = socketpair(family, type, protocol, fd);
 | 
	
		
			
				|  |  |    if (r == 0) {
 | 
	
		
			
				|  |  | +    socket_accounting_lock();
 | 
	
		
			
				|  |  |      if (fd[0] >= 0) {
 | 
	
		
			
				|  |  |        ++n_sockets_open;
 | 
	
		
			
				|  |  |        mark_socket_open(fd[0]);
 | 
	
	
		
			
				|  | @@ -825,6 +856,7 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
 | 
	
		
			
				|  |  |        ++n_sockets_open;
 | 
	
		
			
				|  |  |        mark_socket_open(fd[1]);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    socket_accounting_unlock();
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return r < 0 ? -errno : r;
 | 
	
		
			
				|  |  |  #else
 |