我使用fpFork()
调用编写了一个多线程tcp服务器。工作正常,但在客户端断开连接之后,僵尸进程仍然存在。有一个无限循环,我等待传入连接,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;
我关于函数fpWait()
或fpWaitPid()
,但免费的pascal文档缺乏示例,谷歌搜索它没有价值,因此我甚至不知道如何使用它。
我在FreeBSD上使用fpc 2.6.4。
更新1 经过一些试错测试,阅读手册和讨论,我尝试了一些组合。我将以下函数放在已执行代码的父部分中:
else if pid > 0 then
begin
CloseSocket(ClientSock);
//here
continue;
end;
a)使用WaitProcess(pid)
(等同于fpWaitPid(pid, @Status, 0)
)
使用此父进程等待子进程,但是当父进程正在等待时,它将无法接受另一个连接,直到该子进程终止。
b)使用fpWaitPid(pid, @Status, WNOHANG)
此功能不会阻止程序,但它不会做任何事情。就像功能甚至没有。令人困惑的是,因为我读到的任何内容(它都是用C语言编写的,但它无关紧要,这些函数只是unix调用的包装器)被建议使用它。
此时我不知道会出现什么问题。提前谢谢。
答案 0 :(得分:2)
当子进程结束时,它将一个zombee和系统发送SIGCHLD
信号给父进程。父进程在接受wait
信号时会调用fpwait
(freepascal中的SIGCHLD
)函数。如果父进程调用wait
函数系统发送到子进程的父进程退出代码并擦除它的记录并释放它的pid。
如果父进程不对SIGCHLD
信号做出反应并且(或)不会调用等待功能,那么zombee进程的数量将会增加,直到父进程终止
procedure DoSigChld; cdecl;
var stat : longint;
begin
fpwait(stat);
end;
SignalAction.sa_handler := @DoSigChld;
fpsigaction(SIGCHLD, @SignalAction, nil);