我的多进程应用程序遇到问题,其中主进程创建子进程,并且每个子进程进一步分叉。如果达到分叉的系统限制,导致分叉失败,我实现了一种机制,让子进程向主进程发送 SIGTERM 信号。主进程捕获该信号并继续清理资源(信号、共享内存、消息队列)。
基于信号的清理方法在我的项目的其他部分无缝工作,例如当代码中的 while 循环正确结束时;
示例默认终止:
void run_simulation()
{
while (i <= config_shm->sim_duration)
{
/* Does operations */
i++;
}
kill(getpid(), SIGTERM);
}
SIGTERM 清理:
/* Clean up resources and exit gracefully */
void clean_and_exit()
{
/* Stop child processes */
unlock_semaphore(&sops, sim_sem_id, 0);
/* Terminate child processes */
system(GRACEFUL_SHUTDOWN_SCRIPT);
/*Detach shared memory segments */
detach_shared_memory(config_shm);
detach_shared_memory(stats_shm);
/* Remove shared memory segments */
remove_shared_memory(config_shm_id);
remove_shared_memory(stats_shm_id);
/* Remove semaphores */
remove_semaphore(config_sem_id);
remove_semaphore(stats_sem_id);
remove_semaphore(sync_sem_id);
remove_semaphore(sim_sem_id);
remove_semaphore(inhibitor_sem_id);
/* Remove message queue */
remove_message_queue(msg_queue_id);
/* Freeallocated memory for configuration variables*/
free(config);
}
但是,在分叉失败的情况下使用信号时,我遇到了意想不到的错误。看来在发送信号之前资源就已经被释放了。是否有针对失败分叉的自动清理,或者我的清理过程是否存在问题?
错误消息:
[错误] ipcs/sem.c 行:50 PID = 7022 错误 43(标识符已删除)
[错误] ipcs/msg.c 行:52 PID = 7256 错误 22(无效参数)
[错误] ipcs/msg.c 行:52 PID = 6981 错误 22(无效参数)
...
子叉失败:
pid = fork();
if (pid == -1)
{
kill(getppid(), SIGTERM);
}
else if (pid == 0)
{
/* Child operations*/
}
我正在寻求有关为什么分叉失败后的清理过程可能会导致这些错误以及如何有效解决此问题的见解。此外,我愿意接受关于使用消息队列而不是信号进行通信是否是一种更可靠的方法的建议。
您的清理处理程序调用
system()
,它在内部分叉一个 shell 来运行您的脚本,该脚本可能会分叉其他子进程来运行其中的 shell 命令。这在达到最大分叉数量的情况下不起作用。检查 system()
的退货状态会有所帮助。wait()
与子进程的终止同步,因为您可能会在子进程仍在使用 IPC 时删除它们。