2012-01-17 2 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 프로세스는 부모가 '그것을 할 수있는 다시 시작하려고 그렇게 할 때, 부모 소켓 잡고 나를 왼쪽

티. 그리고 구글 (플러스 스택) 아니다 -

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); 
} 

이 내 마지막 질문에 소켓에 ​​FD_CLOEXEC에 말했지만, 난 어떻게-을 그렇게 이해가 안 : 여기

내 부모 소켓 물건 저에게 많은 도움을 보여줍니다.

내 ServerSocket()에서 FD_CLOEXEC을 수행하면 하위 프로세스를 fork/execl 할 때 소켓이 끊어지지 않습니다.

감사합니다 : D

답변 : 는 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()도 작동하지만 내장 된 사람들과 브라 우니 포인트를 얻을 수는 없습니다.

마지막으로, 처음 세 filedescriptors를 닫은 후에 열려있는 다음 fds가이 세 개가 될 것이라는 보장은 없습니다. 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()'에서 표준 파일 기술자를 닫지 않아야한다는 것에주의하십시오 - 이것들은 자식에 의해 상속 될 것이고, 그렇지 않으면 처음에 그들을 설정하는 것이 이해가되지 않을 것입니다. –