2015-01-18 4 views
0

Я написал многостраничный tcp-сервер, используя вызов fpFork(). Хорошо работает, но после того, как клиент отключается, процесс зомби остается. Существует бесконечный цикл, в котором я жду входящего соединения, fork, передаю это coninction ребенку, который позаботится об этом, а затем выйдет. Однако ребенок остается зомби до тех пор, пока родитель не прекратит свое существование.Паскаль - процесс зомби остается после fork

while True do 
    begin 
    // Accept connection 
    ClientAddrLen := sizeof(ClientAddr); 
    ClientSock := fpaccept(ServerSock, @ClientAddr, @ClientAddrLen); 

    if ClientSock > 0 then // Success? 
    begin 

     Pid := fpFork(); 
     // Error fork 
     if pid < 0 then 
     begin 
      CloseSocket(ClientSock); 
      continue; 
     end 
     // Child process 
     else if pid = 0 then 
     begin 
      CloseSocket(ServerSock); 
      handleClient(ClientSock); 
      CloseSocket(ClientSock); 
      Halt(0); 
     end 
     // parent process 
     else if pid > 0 then 
     begin 
      CloseSocket(ClientSock); 
      continue; 
     end; 
    end; 
end; 

Я headr о функции fpWait() или fpWaitPid() но свободной паскаль документации отсутствуют примеры и прибегая к помощи его ничего не стоит, поэтому я даже не как использовать его. Я использую fpc 2.6.4 на FreeBSD.

Обновление 1 После некоторых пробных испытаний, ознакомления с руководствами и обсуждениями я пробовал некоторые комбинации. Я ставлю следующие функции в родительской части исполняемого кода:

else if pid > 0 then 
    begin 
    CloseSocket(ClientSock); 
    //here 
    continue; 
    end; 

а) Использование WaitProcess(pid) (это equivalet с fpWaitPid(pid, @Status, 0))

С этим родительским процессом ждать ребенка, однако, как родитель ждет его не мог Не принимайте другое соединение, пока ребенок не будет разорван.

б) Использование fpWaitPid(pid, @Status, WNOHANG)

Эта функция не блокирует программу, но это не мешает делать что-нибудь. Подобно этой функции даже нет. Это сбивает с толку, потому что везде я читал об этом (он был закодирован на C, но это неважно, эти функции - только обертки вокруг вызовов unix) было предложено использовать это.

На данный момент я понятия не имею, что может быть неправильным. Заранее спасибо.

+0

Все эти Ф.П. * функции являются обычными функциями UNIX с префиксом «FP», чтобы избежать конфликтов (например, для чтения, записи и открытый) .. fpwaitpid является оберткой ждать, что петли для общих причин, происходит от Ричарда Стивенса IIRC. –

+0

@MarcovandeVoort Хорошая точка, я сделал несколько проб и ошибок, но ничего не работает. Я объясню это в своем вопросе – Heretiiik

+0

Я не являюсь настоящим экспертом в forking-серверах (я предпочитаю подход с потоками), но я бы дважды проверял, соответствует ли ваш сценарий сопоставлению скелетов сервера с письмом, возможно, есть необходимость обнулить ручки или какой-либо другой дополнительной обработки, которая требуется. –

ответ

1

Когда дочерний процесс был завершен, он стал зомби и отправил сигнал SIGCHLD в родительский процесс. Родительский процесс вызовет wait (fpwait in freepascal), если он принимает сигнал SIGCHLD. Если родительский процесс вызывает wait, система функций отправляет родительскому процессу код выхода дочернего процесса и стирает его запись и освобождает его pid.

Если родительский процесс не реагирует на сигналы SIGCHLD и (или) не вызывает функцию ожидания, тогда количество процессов zombee будет умножаться до завершения родительского процесса.

procedure DoSigChld; cdecl; 
var stat : longint; 
begin 
    fpwait(stat); 
end; 

SignalAction.sa_handler := @DoSigChld; 
fpsigaction(SIGCHLD, @SignalAction, nil); 
+0

Это правильный ответ, я не знаю, почему он получил downvoted. Обратите внимание, что настройка SIGCHLD для SIG_IGN работает так же хорошо. См. Http: // www.microhowto.info/howto/reap_zombie_processes_using_a_sigchld_handler.html –

Смежные вопросы