pthreads的和信号处理的C月初结束 [英] pthreads and signal handling C ending early

查看:122
本文介绍了pthreads的和信号处理的C月初结束的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这程序应该是

父只是无限期地等待任何儿童返回(提示,waitpid函数)。
湾孩子设置了两个信号处理(提示,信号),并进入睡眠状态5分钟。
一世。第一信号处理侦听USR1信号,并且在接收它:
1.创建一个线程(提示,pthread_create的)。
一个。基本上,所有的线程需要做的是打招呼和睡眠60
秒。
II。第二信号处理侦听USR2信号,并且在接收它:
1.销毁线程(提示,pthread_cancel可以)。

当此程序接收到的第一信号来创建线程,它输出
 [主题]熟睡的1米[主题]熟睡的1分钟
然后结束,它永远不会等待第二个信号,我究竟做错了什么?

 的#include<&stdio.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / wait.h>
#包括LT&;&unistd.h中GT;
#包括LT&;&pthreads.h中GT;
#包括LT&;&signal.h中GT;线程的pthread_t;void *的温度()
{
    的printf([主题]教授您好\\ n);
    的printf([主题]熟睡的1分钟\\ n);
    睡眠(60);
}
无效handle_USR1(INT X)
{
    int类型;
    的printf([信号]创建线程\\ n);
    S =在pthread_create(安培;螺纹,NULL,&放大器;温度,NULL);
}无效handle_USR2(INT X)
{
    int类型;
    的printf([信号]破坏螺纹,\\ n);
    S = pthread_cancel可以(螺纹);
}INT主要(无效)
{
    INT状态= 0;    如果(叉()!= 0)
    {
     的printf([家长]等待..... \\ n);
     waitpid函数(-1,&放大器;状态,0);
    }
    其他
    {
     的printf([儿童]创建线程:杀-USR1%d个\\ N,GETPID());
     的printf([儿童]结束线程:杀-USR2%d个\\ N,GETPID());
     的printf([儿童]设置信号处理的\\ n);     信号(SIGUSR1,handle_USR1);
     信号(SIGUSR2,handle_USR2);     的printf([儿童]等待信号\\ n);
     睡眠(300);
    }
    返回(0);
}


解决方案

由于查理伯恩斯指出,这两个进程最终退出作为信号的结果,但出于不同的原因。

孩子

在其睡觉,孩子被阻挡在系统调用(实际的系统调用了nanosleep ,用于实施睡眠()功能)。当同时在一个系统调用,则执行相应的信号处理程序处理接收信号,系统调用返回一个错误, EINTR ,这意味着它已经中断和couldn'会履行其职责。然后,您可以决定是否要重新启动系统呼叫。在接收SIGUSR1,由子执行了nanosleep系统呼叫被中断,则处理程序被执行并睡眠()立即返回。请注意什么 3人睡眠表示,有关睡眠的返回值():

 零如果请求的时间已过,或秒数左侧睡,如果呼叫是通过信号处理程序中断。

正确的方法是为孩子检查睡眠的返回值(秒数左侧睡),并为持续时间再次入睡。

不像什么查理伯恩斯指出,waitpid函数()在家长不因为孩子接收信号的回报。它返回因为孩子离开的。它会返回因为孩子,如果孩子没有处理的信号,因而被它(未处理的信号使进程死亡)被杀害的。您可以(也应该)检查使用WIFEXITED宏在描述了它的同伴的人2 waitpid函数。在这名男子页面底部的例子很不错的:

  {做
   W = waitpid函数(CPID,和放大器;状态,WUNTRACED | WCONTINUED);
   如果(W == -1){
       PERROR(waitpid函数);
       出口(EXIT_FAILURE);
   }   如果(WIFEXITED(状态)){
       的printf(退出状态=%d个\\ N,WEXITSTATUS(状态));
   }否则如果(WIFSIGNALED(状态)){
       的printf(通过信号%d个\\ n封杀,WTERMSIG(状态));
   }否则如果(WIFSTOPPED(状态)){
       的printf(通过信号%d个\\ n停止,WSTOPSIG(状态));
   }否则如果(WIFCONTINUED(状态)){
       的printf(续\\ n);
   }
}而(WIFEXITED(状态)及!&安培;!WIFSIGNALED(状态));

基本上,这是什么code的作用是伺候孩子,直到它已正常退出或已退出,因为未处理的信号。对你来说,这将是一个不错的主意父检查状态变量,以确保waitpid函数返回,因为事件的预计(孩子退出),而不是别的东西。

This program is supposed to

The parent simply waits indefinitely for any child to return (hint, waitpid). b. The child sets up two signal handlers (hint, signal) and goes to sleep for 5 minutes. i. The first signal handler listens for the USR1 signal, and upon receiving it: 1. Creates a thread (hint, pthread_create). a. Basically, all that the thread needs to do is "say hello" and sleep for 60 seconds. ii. The second signal handler listens for the USR2 signal, and upon receiving it: 1. Destroys the thread (hint, pthread_cancel).

When this program receives the first signal to create the thread, it outputs "[thread] sleeping for 1 m[thread] sleeping for 1 minute" and then ends, it never waits for the 2nd signal, what am i doing wrong?

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

pthread_t thread;

void* temp()
{
    printf("[thread] hello professor\n");
    printf("[thread] sleeping for 1 minute\n");
    sleep(60);
}
void handle_USR1(int x)
{
    int s;
    printf("[signal] creating the thread\n");
    s = pthread_create(&thread, NULL, &temp, NULL);
}

void handle_USR2(int x)
{
    int s;
    printf("[signal] destroying the thread\n");
    s = pthread_cancel(thread);
}

int main(void)
{
    int status = 0;

    if(fork() != 0)
    {
     printf("[parent] waiting.....\n");
     waitpid(-1, &status, 0);
    }
    else
    {
     printf("[child] to create the thread: kill -USR1 %d\n", getpid());
     printf("[child] to end the thread: kill -USR2 %d\n", getpid());
     printf("[child] setting up signal handlers\n");

     signal(SIGUSR1, handle_USR1);
     signal(SIGUSR2, handle_USR2);

     printf("[child] waiting for signals\n");
     sleep(300);
    }
    return (0);
}

解决方案

As Charlie Burns pointed out, both processes eventually exit as a consequence of the signal, but for different reasons.

Child

During its sleep, the child is blocked in a system call (the actual system call is nanosleep, used to implement the sleep() function). When a process receives a signal while in a system call, the corresponding signal handler is executed and the system call returns an error, EINTR, which means it has been interrupted and couldn't fulfill its duty. You can then decide if you want to restart the system call or not. Upon receiving SIGUSR1, the nanosleep system call executed by the child is interrupted, the handler is executed and sleep() returns immediately. Notice what man 3 sleep says about the return value of sleep():

Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a signal handler.

The correct way would be for the child to check for the return value of sleep (number of seconds left to sleep), and sleep again for that duration.

Parent

Unlike what Charlie Burns pointed out, waitpid() in the parent does not return because of the child receiving a signal. It returns because of the child exiting. It would return because of the child IF the child did not handle the signal, and thus was killed by it (an unhandled signal causes the process to die). You can (and should) check that using the WIFEXITED macro and its companions as described in man 2 waitpid. The example at the bottom of this man page is very good:

do {
   w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
   if (w == -1) {
       perror("waitpid");
       exit(EXIT_FAILURE);
   }

   if (WIFEXITED(status)) {
       printf("exited, status=%d\n", WEXITSTATUS(status));
   } else if (WIFSIGNALED(status)) {
       printf("killed by signal %d\n", WTERMSIG(status));
   } else if (WIFSTOPPED(status)) {
       printf("stopped by signal %d\n", WSTOPSIG(status));
   } else if (WIFCONTINUED(status)) {
       printf("continued\n");
   }
} while (!WIFEXITED(status) && !WIFSIGNALED(status));

Basically, what this code does is wait on the child until it has exited normally or has exited because of an unhandled signal. In your case, it would be a good idea for the parent to check the status variable to make sure that waitpid returned because of the event it expects (a child exiting) and not something else.

这篇关于pthreads的和信号处理的C月初结束的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆