Ich hatte auch dieses Problem. Sie haben ein Dateihandle-Leck. Sie können dies debuggen, indem Sie eine Liste aller geöffneten Dateihandles (auf POSIX-Systemen) ausdrucken:
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 ";
if ( fl_flags & O_APPEND ) cerr << "append ";
if ( fl_flags & O_NONBLOCK ) cerr << "nonblock ";
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 << ") ";
}
}
Wenn Sie alle geöffneten Dateien ausgeben, können Sie schnell herausfinden, wo sich das Leck Ihres Dateihandles befindet.
Wenn Ihr Server Unterprozesse erzeugt. Wenn es sich beispielsweise um einen Server im Fork-Stil handelt oder wenn Sie andere Prozesse erzeugen (z. B. über CGI), müssen Sie sicherstellen, dass Ihre Dateihandles mit "cloexec" erstellt werden - sowohl für echte Dateien als auch für Sockets.
Ohne cloexec werden jedes Mal, wenn Sie gabeln oder spawnen, alle geöffneten Dateihandles im untergeordneten Prozess geklont.
Es ist auch sehr einfach, Netzwerk-Sockets nicht zu schließen - z. B. sie einfach zu verlassen, wenn die Remote-Partei die Verbindung trennt. Dies wird Griffe wie verrückt auslaufen lassen.