2012-01-17 4 views
1

私のアプリでコマンドをバックグラウンドしようとすると問題が発生しましたので、私はtold hereを二重フォークしていくつかの設定をクリアするので、これは私の結果でした:C++ ServerSocket()、FD_CLOEXEC、fork()&execl()

if((pid = fork()) < 0) 
    perror("Error with Fork()"); 
else if(pid > 0) { 
    return ""; 
} 
if (setsid()==-1) { 
    Log("failed to become a session leader"); 
} 

if (chdir("/") == -1) { 
    Log("failed to change working directory"); 
} 

umask(0); 
close(STDIN_FILENO); 
close(STDOUT_FILENO); 
close(STDERR_FILENO); 
if (open("/dev/null",O_RDONLY) == -1) { 
    Log("failed to reopen stdin"); 
} 
if (open("/dev/null",O_WRONLY) == -1) { 
    Log("failed to reopen stdout"); 
} 
if (open("/dev/null",O_RDWR) == -1) { 
    Log("failed to reopen stderr"); 
} 

signal(SIGHUP, SIG_IGN); 
Log("No return, forking.."); 
if((pid = fork()) < 0) 
    perror("Error with Fork()"); 
else if(pid > 0) { 
    return ""; 
} else {   
    if(execl("/bin/bash", "/bin/bash", "-c", cmddo, (char*) 0) < 0) perror("execl()"); 
    exit(0); 
} 

ダブル「することができ、親が閉じているときにexecl'd procを停止する問題を修正しましたが、それは親ソケット上に保持execl'dプロセスで私を残し、その親はそれを再度起動しようとするとフォークt。私は私の最後の質問でソケットにFD_CLOEXECに言われた

ServerSocket server(listenport); 
while(true) 
{ 
    ServerSocket* new_sock = new ServerSocket(); 

    server.accept (*new_sock); 

    pthread_t thread; 
    int rc = pthread_create(&thread, NULL, &LoadThread, (void*)(new_sock)); 

    if (rc) Log_warn("Fatal Error: pthread_create() #%d", rc); 
    pthread_detach(thread); 
} 

が、私はそれを行う方法を、理解していない - とGoogle(プラススタックが)ではありません。ここで

は私の親ソケットのものですそれについて私に多くの助けを示してくれました。

ServerSocket()でFD_CLOEXECを実行すると、サブプロセスをfork/execlするとソケットがハングアップしません。

ありがとう:D

ANSWER: からFD年代をクリアするには、以下の言われたよう - 私のコードは、実際にこれを持っていた、そしてそれは私の仕事:

struct rlimit  rl; 
int     i; 

if (rl.rlim_max == RLIM_INFINITY) 
    rl.rlim_max = 1024; 

for (i = 0; (unsigned) i < rl.rlim_max; i++) 
    close(i); 

答えて

2

FD_CLOEXECはそれができフラグですファイル記述子に設定されます。その効果は、ハンドルを保持するプロセスがexec()を呼び出すと、記述子が閉じられることです。

フラグを設定するために使用

fcntl(fd, F_SETFD, (long)FD_CLOEXEC); 

。これが機能するには、実際のファイル記述子にアクセスする必要があります。

setsid()また、親プロセスグループとの関連付けを解除するのに十分であり、fork()も有効ですが、埋め込みユーザーにはブラニーポイントはありません。

最後に、最初の3つのfiledescriptorを閉じた後、次のfdsが3つになるという保証はありません。 ServerSocketを()がFDを作るん - 私が2番目と3番目の点が、私の最初の、そして主なものを理解しないと思いますが、私はまだ混乱しています

fd newstdin = open(...); 
if(dup2(newstdin, STDIN_FILENO) != 0) { /* handle error */ } 
close(newstdin); 
+0

を使用することが良いですか?私のアプリケーションの唯一のfdはデーモンに設定されているとき、私はすでにFD_CLOEXECです。 fd0 = open( "/ dev/null"、O_RDWR); \t fcntl(fd0、F_SETFD、FD_CLOEXEC);ありがとう! –

+0

ServerSocketには内部的にfdがあります。これは実装の詳細であり、原則としてアプリケーションに関係しないはずですが、通常は抽象化を解除する方法があります(あるいは、ServerSocketにclose-on-execフラグを設定するよう教えることができますか?そうするべき正しいこと)。 –

+0

'exec()'の標準ファイル記述子を閉じるべきではないことに注意してください。これらは子によって継承されるものです。そうでなければ、最初にそれらを設定するのは意味がありません。 –