为什么要关闭这个应用程序?

huangapple go评论65阅读模式
英文:

Why is this application being closed?

问题

处理信号是否会以任何方式关闭应用程序?我的目标是在时间用尽时执行某些操作,但在循环中被卡住,直到用户输入q或找到EOF,但由于某种原因,一旦收到信号,应用程序似乎根本不执行循环,只是打印printf("returning from main!!\n");并退出应用程序。我错过了什么?我该如何修复这个问题?

以下是完整的代码:

#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ucontext.h>
#include <unistd.h>

void thread_signal_handler(int signal)
{
    // 线程的时间片用尽,切换到另一个线程
    // ...
    printf("时间用尽了!!!\n");
}

int main()
{
    // 为线程的时间片设置信号处理程序
    struct sigaction sa;
    sa.sa_handler = thread_signal_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGALRM, &sa, NULL);

    // 为线程的时间片设置定时器
    struct itimerval timer;
    timer.it_value.tv_sec = 5;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &timer, NULL);

    while (1)
    {
        int ch = getchar();
        if (ch == 'q' || ch == EOF)
            break;
    }
    printf("从main返回!!\n");
    return 0;
}

Hope this helps!

英文:

Does handling signals make the application close in anyway? my goal is to do some action when time run out but get stuck in the loop, until the user enter q or EOF is found but for some reason as soon the singal is received, the application seem to not execute the loop at all just print printf("returning from main!!\n"); and exit from the application. What am I misisng? how do i fix that?

here's the full code:

#include &lt;signal.h&gt;
#include &lt;sys/time.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stddef.h&gt;
#include &lt;ucontext.h&gt;
#include &lt;unistd.h&gt;

void thread_signal_handler(int signal)
{
    // Thread&#39;s time slice has run out, switch to another thread
    // ...
    printf(&quot;time run out!!!\n&quot;);
}

int main()
{
    // Set up the signal handler for the thread&#39;s time slice
    struct sigaction sa;
    sa.sa_handler = thread_signal_handler;
    sigemptyset(&amp;sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGALRM, &amp;sa, NULL);

    // Set up the timer for the thread&#39;s time slice
    struct itimerval timer;
    timer.it_value.tv_sec = 5;
    timer.it_value.tv_usec = 0;
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 0;
    setitimer(ITIMER_REAL, &amp;timer, NULL);

    while (1)
    {
        int ch = getchar();
        if(ch == &#39;q&#39; || ch == EOF) break;
    }
    printf(&quot;returning from main!!\n&quot;);
    return 0;
}

答案1

得分: 2

信号处理程序在getchar等待用户输入时被触发。

信号处理程序返回后,getchar返回EOF,errno设置为EINTR,表明调用被中断。这导致循环退出。

英文:

The signal handler is getting fired while getchar is waiting for user input.

After the signal handler returns, getchar returns EOF and errno is set to EINTR, indicating that the call was interrupted. This causes your loop to exit.

答案2

得分: 2

如果发生读取错误,流的错误指示器将被设置,getchar() 将返回EOF,并设置errno以指示错误。

getchar() 函数在需要读取数据且出现以下情况时会失败:

  • EINTR

读取操作由于接收到信号而被终止,且没有数据被传输。

信号处理程序完成后,执行将返回到信号中断它的点。然后,getchar() 返回EOF,因为它被信号中断,并将errno设置为EINTR,这将导致while循环退出。

话虽如此,您的代码会触发未定义行为,因为printf() 是异步信号不安全的,也就是说,不能安全地在信号处理程序内调用它(无论是在C标准中还是在POSIX标准中)。

尽管如此,POSIX标准定义了write() 系统调用是异步信号安全的,可以用来替代printf()

write(STDOUT_FILENO, "time run out!!!\n", 17);
英文:

> If a read error occurs, the error
> indicator for the stream shall be set, getchar() shall return EOF,
> and shall set errno to indicate the error.

The getchar() function shall fail if data needs to be read and:

> EINTR
>
> The read operation was terminated due to the receipt of a
> signal, and no data was transferred.

After the signal handler completes, execution returns to the point right where the signal interrupted it. getchar() then returns EOF because it was interrupted by a signal, and sets errno to EINTR, which causes the while loop to exit.

That being said, your code simply invokes undefined behaviour because printf() is async-signal-unsafe, i.e. it can't be called safely inside a signal handler. (Neither in the C standard, nor the POSIX standard).

Though, the POSIX standard does define the write() syscall to be async-signal-safe that can be used instead of printf():

write (STDOUT_FILENO, &quot;time run out!!!\n&quot;, 17);

huangapple
  • 本文由 发表于 2023年2月24日 11:34:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75552389.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定