- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
这是我用来检查这个的代码:
void handler(int n) {
printf("handler %d\n", n);
int status;
if (wait(&status) < 0)
printf("%s\n", strerror(errno));
}
int main() {
struct sigaction sig;
sigemptyset(&sig.sa_mask);
sig.sa_handler = handler;
sig.sa_flags = 0;
sig.sa_restorer = NULL;
struct sigaction sigold;
sigaction(SIGCHLD, &sig, &sigold);
pid_t pid;
int status;
printf("before fork\n");
if ((pid = fork()) == 0) {
_exit(127);
} else if (pid > 0) {
printf("before waitpid\n");
if (waitpid(pid, &status, 0) < 0)
printf("%s\n", strerror(errno));
printf("after waitpid\n");
}
printf("after fork\n");
return 0;
}
输出是:
before fork
before waitpid
handler 17
No child processes
after waitpid
after fork
所以,我认为 waitpid 会阻塞 SIGCHLD 并等待子进程终止,一旦子进程终止,它会做一些事情并在它返回之前解除对 SIGCHLD 的阻塞,这就是为什么我们看到“没有子进程” 错误和 "after waitpid" 是在 "handler 17" 之后,我说得对吗?如果不是,真相是什么?如何解释输出序列?是否有 Linux 规范或类似规范可供检查?
最佳答案
进程的退出信息只能收集一次。您的输出显示信号处理程序在您的代码处于 waitpid()
时被调用,但处理程序调用 wait()
并收集子项的信息(您抛出的不报告而离开)。然后,当您返回 waitpid()
时,已收集到子进程退出状态,因此 waitpid()
没有任何可报告的内容,因此没有子进程' 错误。
这是对您的程序的改编。它通过在信号处理函数中使用 printf()
来滥用功能,但尽管如此,它似乎仍能正常工作,在运行 macOS Sierra 10.12.4(使用 GCC 7.1.0 编译)的 Mac 上进行测试。
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
static void handler(int n)
{
printf("handler %d\n", n);
int status;
int corpse;
if ((corpse = wait(&status)) < 0)
printf("%s: %s\n", __func__, strerror(errno));
else
printf("%s: child %d exited with status 0x%.4X\n", __func__, corpse, status);
}
int main(void)
{
struct sigaction sig = { 0 };
sigemptyset(&sig.sa_mask);
sig.sa_handler = handler;
sig.sa_flags = 0;
sigaction(SIGCHLD, &sig, NULL);
pid_t pid;
printf("before fork\n");
if ((pid = fork()) == 0)
{
_exit(127);
}
else if (pid > 0)
{
printf("before waitpid\n");
int status;
int corpse;
while ((corpse = waitpid(pid, &status, 0)) > 0 || errno == EINTR)
{
if (corpse < 0)
printf("loop: %s\n", strerror(errno));
else
printf("%s: child %d exited with status 0x%.4X\n", __func__, corpse, status);
}
if (corpse < 0)
printf("%s: %s\n", __func__, strerror(errno));
printf("after waitpid loop\n");
}
printf("after fork\n");
return 0;
}
示例输出:
before fork
before waitpid
handler 20
handler: child 29481 exited with status 0x7F00
loop: Interrupted system call
main: No child processes
after waitpid loop
after fork
状态值 0x7F00 是 _exit(127)
的正常编码。 macOS 和 Linux 的信号编号不同;这是完全允许的。
为了让代码在 Linux(Centos 7 和 Ubuntu 16.04 LTS 用于测试)上编译,分别使用 GCC 4.8.5(几乎是过时的 - 当前版本是 GCC 7.1.0)和 5.4.0,使用命令行:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes -Wold-style-definition sg59.c -o sg59
$
我在第一个 header 之前添加了 #define _XOPEN_SOURCE 800
,并使用了:
struct sigaction sig;
memset(&sig, '\0', sizeof(sig));
使用 GCC 4.8.5 初始化结构。这种恶作剧有时是避免编译器警告的痛苦必需品。我注意到,尽管 #define
是公开 POSIX 符号所必需的,但初始化程序 (struct sigaction sig = { 0 };
) 已被 GCC 5.4.0 毫无问题地接受。
然后当我运行该程序时,我得到与 cong 非常相似的输出报告进入 comment :
before fork
before waitpid
handler 17
handler: No child processes
main: child 101681 exited with status 0x7F00
main: No child processes
after waitpid loop
after fork
确实奇怪的是,在 Linux 上,进程被发送了一个 SIGCHLD 信号,但是 wait()
不能在信号处理程序中等待它。这至少是违反直觉的。
我们可以讨论 waitpid()
的第一个参数是 pid
而不是 0
有多重要;自第一次从 child 那里收集信息以来,该错误在循环的第二次迭代中是不可避免的。实际上,这里并不重要。一般而言,最好使用 waitpid(0, &status, WNOHANG)
或附近 — 根据上下文,0
而不是 WNOHANG
可能会更好。
关于c - wait 和 waitpid 在 Linux 中返回时会阻塞 SIGCHLD 并解除阻塞吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43949142/
如何确定操作表何时已关闭或已被驳回? 我关注了这个主题Fitting a UIDatePicker into a UIActionSheet并向操作表添加了选择器 View 。但是,当操作表仍处于打开
在关闭 UIActivityViewController 后如何调用操作?例如,如果我想在用户关闭 UIActivityViewController 后更改一段文本。 谢谢大家! 最佳答案 使用它的完
我的代码中有以下几行: func searchBarTextDidBeginEditing(searchBar: UISearchBar) { searchBar.showsCancelBut
像这样使用 UIAlertController 时: var alert = UIAlertController(title: "Core Location", message: "Loca
我正在使用 UITableViewController 来显示要编辑的项目列表。点击一行后,用户将转到 View Controller 以编辑数据。 当他们通过默认 <(后退)按钮退出编辑屏幕时,我想
我有一个自定义的 UIImagePickerController ,它工作得很好,只是我面临一个我认为应该相当简单的问题 - 我只是还没有找到解决方案。 触摸我自定义添加的“照片”按钮后,我将其定位到
我在显示 UIMenuController 的表格 View 单元格上实现了一个长按手势识别器,当菜单显示时,相应的表格 View 单元格被选中,这是我的要求。但问题是当我触及 UIMenuContr
我有: df = pd.DataFrame({'col1': ['asdf', 'xy', 'q'], 'col2': [1, 2, 3]}) col1 col2 0 asdf 1
我正在尝试解除实时事件的绑定(bind)(已尝试使用 .live 和 .delegate)。 当我想解除绑定(bind)时,我有 3 个不同的选项:解除绑定(bind) "click"、解除绑定(bi
我正在使用 spock、geb 和 WebDriver 编写测试脚本。该脚本在不安全的页面上提交表单。该页面提交到安全的 HTTPS URL。 Firefox 对此显示警告,特别是: 这会导致以下错误
我有两个 s 和每个 ng-repeat,但都对其子元素执行相同的操作,如下所示: {{item.name}} {{item.name}} 想象一下,有两种类型的数据集,要渲染
我构建了一个通过 APIHiJack 连接到 Win32 TextOut 函数的应用程序。当应用程序启动时,DLL 将按预期注入(inject),并且我的新 TextOut 函数被成功调用。 目前,关
我遇到了一次非常奇怪的崩溃,这是回溯。 * thread #1: tid = 0x2403, 0x3379516c CoreFoundation`CFHash + 8, stop reason = E
我有一个 FirstViewController 和一个 SecondViewController。它们的 UINavigationBar 有不同的颜色。当我显示 SecondViewControll
抱歉,如果我在文档中遗漏了一些内容,但无论如何我都找不到阻止在 SweetAlert 2 中关闭对话框的方法,这些将不起作用: await Swal.fire({
有没有人见过这个?在 iPad 模拟器中,我有一个 About View Controller 。我想以模态方式呈现它,并让用户单击关闭按钮。 更复杂的是,我有一个主视图 Controller ,它显
我有 3 个 View Controller - BaseViewController->AviewController->BviewController。 AviewController 以模态方式
如果我在对象上有一个事件聚合器, eventAggregator: _.extend({}, Backbone.Events), 对于模态视图,我基本上让模态视图的呈现者监听模态视图的事件。 this
我有几个 View Controller 。如果 Alert View 被确认,我需要返回到第一个 View Controller。如果没有 unwind Segue,我会这样做: @IBAction
我有一个为 SharePoint 编写的 Accordion 菜单: parent.click(function(event) { event.preventDefault(); va
我是一名优秀的程序员,十分优秀!