(trunk libt) #4315 "Transmission 2.31 crashes (segfaults) immediately after launch" -- remove the "max-open-files" code.

max-open-files might have been a nice configuration option once, but (1) we've never advertised it in the gui apps, and (2) the crazy cases are causing more trouble than this feature is worth. It's more complicated now after #4164 -- see #4294, #4311, and this ticket.
This commit is contained in:
Jordan Lee 2011-06-24 22:39:20 +00:00
parent f5815a89bf
commit 35fb00fd9e
5 changed files with 55 additions and 148 deletions

View File

@ -10,10 +10,6 @@
* $Id$
*/
#ifndef WIN32
#define HAVE_GETRLIMIT
#endif
#ifdef HAVE_POSIX_FADVISE
#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
@ -509,28 +505,56 @@ fileset_get_empty_slot( struct tr_fileset * set )
return cull;
}
static int
fileset_get_size( const struct tr_fileset * set )
/***
****
**** Startup / Shutdown
****
***/
struct tr_fdInfo
{
return set ? set->end - set->begin : 0;
int peerCount;
struct tr_fileset fileset;
};
static void
ensureSessionFdInfoExists( tr_session * session )
{
assert( tr_isSession( session ) );
if( session->fdInfo == NULL )
{
const int TR_MAX_OPEN_FILES = 32;
struct tr_fdInfo * i = tr_new0( struct tr_fdInfo, 1 );
fileset_construct( &i->fileset, TR_MAX_OPEN_FILES );
session->fdInfo = i;
}
}
void
tr_fdClose( tr_session * session )
{
if( session && session->fdInfo )
{
struct tr_fdInfo * i = session->fdInfo;
fileset_destruct( &i->fileset );
tr_free( i );
session->fdInfo = NULL;
}
}
/***
****
***/
struct tr_fdInfo
{
int socket_count;
int socket_limit;
int public_socket_limit;
struct tr_fileset fileset;
};
static struct tr_fileset*
get_fileset( tr_session * session )
{
return session && session->fdInfo ? &session->fdInfo->fileset : NULL;
if( !session )
return NULL;
ensureSessionFdInfoExists( session );
return &session->fdInfo->fileset;
}
void
@ -635,21 +659,20 @@ tr_fdSocketCreate( tr_session * session, int domain, int type )
{
int s = -1;
struct tr_fdInfo * gFd;
assert( tr_isSession( session ) );
assert( session->fdInfo != NULL );
ensureSessionFdInfoExists( session );
gFd = session->fdInfo;
if( gFd->socket_count < gFd->socket_limit )
if( gFd->peerCount < session->peerLimit )
if(( s = socket( domain, type, 0 )) < 0 )
if( sockerrno != EAFNOSUPPORT )
tr_err( _( "Couldn't create socket: %s" ), tr_strerror( sockerrno ) );
if( s > -1 )
++gFd->socket_count;
++gFd->peerCount;
assert( gFd->socket_count >= 0 );
assert( gFd->peerCount >= 0 );
if( s >= 0 )
{
@ -678,10 +701,10 @@ tr_fdSocketAccept( tr_session * s, int sockfd, tr_address * addr, tr_port * port
struct sockaddr_storage sock;
assert( tr_isSession( s ) );
assert( s->fdInfo != NULL );
assert( addr );
assert( port );
ensureSessionFdInfoExists( s );
gFd = s->fdInfo;
len = sizeof( struct sockaddr_storage );
@ -689,10 +712,10 @@ tr_fdSocketAccept( tr_session * s, int sockfd, tr_address * addr, tr_port * port
if( fd >= 0 )
{
if( ( gFd->socket_count < gFd->socket_limit )
if( ( gFd->peerCount < s->peerLimit )
&& tr_address_from_sockaddr_storage( addr, port, &sock ) )
{
++gFd->socket_count;
++gFd->peerCount;
}
else
{
@ -716,108 +739,9 @@ tr_fdSocketClose( tr_session * session, int fd )
if( fd >= 0 )
{
tr_netCloseSocket( fd );
--gFd->socket_count;
--gFd->peerCount;
}
assert( gFd->socket_count >= 0 );
assert( gFd->peerCount >= 0 );
}
}
/***
****
**** Startup / Shutdown
****
***/
static void
ensureSessionFdInfoExists( tr_session * session )
{
assert( tr_isSession( session ) );
if( session->fdInfo == NULL )
session->fdInfo = tr_new0( struct tr_fdInfo, 1 );
}
void
tr_fdClose( tr_session * session )
{
struct tr_fdInfo * gFd = session->fdInfo;
if( gFd != NULL )
{
fileset_destruct( &gFd->fileset );
tr_free( gFd );
}
session->fdInfo = NULL;
}
/***
****
***/
int
tr_fdGetFileLimit( tr_session * session )
{
return fileset_get_size( get_fileset( session ) );
}
void
tr_fdSetFileLimit( tr_session * session, int limit )
{
int max;
/* This is a vaguely arbitrary number.
It takes announcer.c's MAX_CONCURRENT_TASKS into account,
plus extra positions for the listening sockets,
plus a few more just to be safe */
const int buffer_slots = 128;
ensureSessionFdInfoExists( session );
max = FD_SETSIZE - session->fdInfo->socket_limit - buffer_slots;
if( limit > max )
limit = max;
if( limit != tr_fdGetFileLimit( session ) )
{
struct tr_fileset * set = get_fileset( session );
fileset_destruct( set );
fileset_construct( set, limit );
}
}
void
tr_fdSetPeerLimit( tr_session * session, int socket_limit )
{
struct tr_fdInfo * gFd;
ensureSessionFdInfoExists( session );
gFd = session->fdInfo;
#ifdef HAVE_GETRLIMIT
{
struct rlimit rlim;
const int NOFILE_BUFFER = 512;
const int open_max = MIN( FD_SETSIZE, sysconf( _SC_OPEN_MAX ) );
getrlimit( RLIMIT_NOFILE, &rlim );
rlim.rlim_cur = MAX( 1024, open_max );
rlim.rlim_cur = MIN( rlim.rlim_cur, rlim.rlim_max );
setrlimit( RLIMIT_NOFILE, &rlim );
tr_dbg( "setrlimit( RLIMIT_NOFILE, %d ); FD_SETSIZE = %d", (int)rlim.rlim_cur, FD_SETSIZE );
gFd->socket_limit = MIN( socket_limit, (int)rlim.rlim_cur - NOFILE_BUFFER );
}
#else
gFd->socket_limit = socket_limit;
#endif
gFd->public_socket_limit = socket_limit;
tr_dbg( "socket limit is %d", gFd->socket_limit );
}
int
tr_fdGetPeerLimit( const tr_session * session )
{
return session && session->fdInfo ? session->fdInfo->public_socket_limit : -1;
}

View File

@ -22,12 +22,6 @@
* @{
*/
void tr_fdSetFileLimit( tr_session * session, int limit );
int tr_fdGetFileLimit( tr_session * session );
void tr_fdSetGlobalPeerLimit( tr_session * session, int limit );
/***
****
***/
@ -125,9 +119,4 @@ void tr_fdSocketClose( tr_session * session, int s );
**********************************************************************/
void tr_fdClose( tr_session * session );
void tr_fdSetPeerLimit( tr_session * session, int n );
int tr_fdGetPeerLimit( const tr_session * );
/* @} */

View File

@ -319,7 +319,6 @@ tr_sessionGetDefaultSettings( tr_benc * d )
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_getDefaultDownloadDir( ) );
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, false );
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, TR_MSG_INF );
tr_bencDictAddInt ( d, TR_PREFS_KEY_OPEN_FILE_LIMIT, atoi( TR_DEFAULT_OPEN_FILE_LIMIT_STR ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, atoi( TR_DEFAULT_PEER_LIMIT_GLOBAL_STR ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, atoi( TR_DEFAULT_PEER_LIMIT_TORRENT_STR ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, atoi( TR_DEFAULT_PEER_PORT_STR ) );
@ -383,8 +382,7 @@ tr_sessionGetSettings( tr_session * s, struct tr_benc * d )
tr_bencDictAddStr ( d, TR_PREFS_KEY_INCOMPLETE_DIR, tr_sessionGetIncompleteDir( s ) );
tr_bencDictAddBool( d, TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED, tr_sessionIsIncompleteDirEnabled( s ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_MSGLEVEL, tr_getMessageLevel( ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_OPEN_FILE_LIMIT, tr_fdGetFileLimit( s ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, tr_sessionGetPeerLimit( s ) );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, s->peerLimit );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_LIMIT_TORRENT, s->peerLimitPerTorrent );
tr_bencDictAddInt ( d, TR_PREFS_KEY_PEER_PORT, tr_sessionGetPeerPort( s ) );
tr_bencDictAddBool( d, TR_PREFS_KEY_PEER_PORT_RANDOM_ON_START, s->isPortRandom );
@ -829,11 +827,8 @@ sessionSetImpl( void * vdata )
if( tr_bencDictFindBool( settings, TR_PREFS_KEY_PORT_FORWARDING, &boolVal ) )
tr_sessionSetPortForwardingEnabled( session, boolVal );
/* file and peer socket limits */
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_PEER_LIMIT_GLOBAL, &i ) )
tr_fdSetPeerLimit( session, i );
if( tr_bencDictFindInt( settings, TR_PREFS_KEY_OPEN_FILE_LIMIT, &i ) )
tr_fdSetFileLimit( session, i );
session->peerLimit = i;
/**
**/
@ -1584,11 +1579,11 @@ tr_sessionClearAltSpeedFunc( tr_session * session )
***/
void
tr_sessionSetPeerLimit( tr_session * session, uint16_t maxGlobalPeers )
tr_sessionSetPeerLimit( tr_session * session, uint16_t n )
{
assert( tr_isSession( session ) );
tr_fdSetPeerLimit( session, maxGlobalPeers );
session->peerLimit = n;
}
uint16_t
@ -1596,7 +1591,7 @@ tr_sessionGetPeerLimit( const tr_session * session )
{
assert( tr_isSession( session ) );
return tr_fdGetPeerLimit( session );
return session->peerLimit;
}
void

View File

@ -129,6 +129,7 @@ struct tr_session
struct evdns_base * evdns_base;
struct tr_event_handle * events;
uint16_t peerLimit;
uint16_t peerLimitPerTorrent;
int uploadSlotsPerTorrent;

View File

@ -148,7 +148,6 @@ const char* tr_getDefaultDownloadDir( void );
#define TR_DEFAULT_BIND_ADDRESS_IPV4 "0.0.0.0"
#define TR_DEFAULT_BIND_ADDRESS_IPV6 "::"
#define TR_DEFAULT_OPEN_FILE_LIMIT_STR "32"
#define TR_DEFAULT_RPC_WHITELIST "127.0.0.1"
#define TR_DEFAULT_RPC_PORT_STR "9091"
#define TR_DEFAULT_RPC_URL_STR "/transmission/"
@ -180,7 +179,6 @@ const char* tr_getDefaultDownloadDir( void );
#define TR_PREFS_KEY_INCOMPLETE_DIR "incomplete-dir"
#define TR_PREFS_KEY_INCOMPLETE_DIR_ENABLED "incomplete-dir-enabled"
#define TR_PREFS_KEY_MSGLEVEL "message-level"
#define TR_PREFS_KEY_OPEN_FILE_LIMIT "open-file-limit"
#define TR_PREFS_KEY_PEER_LIMIT_GLOBAL "peer-limit-global"
#define TR_PREFS_KEY_PEER_LIMIT_TORRENT "peer-limit-per-torrent"
#define TR_PREFS_KEY_PEER_PORT "peer-port"