У меня тоже была эта проблема. У вас есть утечка дескриптора файла. Вы можете отладить это, распечатав список всех дескрипторов открытых файлов (в системах POSIX):
void showFDInfo()
{
s32 numHandles = getdtablesize();
for ( s32 i = 0; i < numHandles; i++ )
{
s32 fd_flags = fcntl( i, F_GETFD );
if ( fd_flags == -1 ) continue;
showFDInfo( i );
}
}
void showFDInfo( s32 fd )
{
char buf[256];
s32 fd_flags = fcntl( fd, F_GETFD );
if ( fd_flags == -1 ) return;
s32 fl_flags = fcntl( fd, F_GETFL );
if ( fl_flags == -1 ) return;
char path[256];
sprintf( path, "/proc/self/fd/%d", fd );
memset( &buf[0], 0, 256 );
ssize_t s = readlink( path, &buf[0], 256 );
if ( s == -1 )
{
cerr << " (" << path << "): " << "not available";
return;
}
cerr << fd << " (" << buf << "): ";
if ( fd_flags & FD_CLOEXEC ) cerr << "cloexec ";
// file status
if ( fl_flags & O_APPEND ) cerr << "append ";
if ( fl_flags & O_NONBLOCK ) cerr << "nonblock ";
// acc mode
if ( fl_flags & O_RDONLY ) cerr << "read-only ";
if ( fl_flags & O_RDWR ) cerr << "read-write ";
if ( fl_flags & O_WRONLY ) cerr << "write-only ";
if ( fl_flags & O_DSYNC ) cerr << "dsync ";
if ( fl_flags & O_RSYNC ) cerr << "rsync ";
if ( fl_flags & O_SYNC ) cerr << "sync ";
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = 0;
fl.l_start = 0;
fl.l_len = 0;
fcntl( fd, F_GETLK, &fl );
if ( fl.l_type != F_UNLCK )
{
if ( fl.l_type == F_WRLCK )
cerr << "write-locked";
else
cerr << "read-locked";
cerr << "(pid:" << fl.l_pid << ") ";
}
}
Выгрузив все открытые файлы, вы быстро выясните, где находится утечка вашего дескриптора файла.
Если ваш сервер порождает подпроцессы. Например. если это сервер в стиле 'fork', или если вы запускаете другие процессы (например, через cgi), вы должны обязательно создать свои файловые дескрипторы с помощью «cloexec» - как для реальных файлов, так и для сокетов.
Без cloexec, каждый раз, когда вы запускаете или порождаете, все дескрипторы открытых файлов клонируются в дочернем процессе.
Также очень просто не закрывать сетевые сокеты - например, просто оставив их, когда удаленная сторона отключится. Это будет течь ручками, как сумасшедшие.