如何通过信号留下无限循环?

时间:2018-01-05 15:09:12

标签: c signals

如果我有这样的话。

#include <signal.h>
#include <stdio.h>

void signalquit(int sig)
{
   printf("\nQuitting..\n");
   (void)signal(SIGINT, SIG_DFL);
   //How to return?
}

int main(void)
{
   (void)signal(SIGINT, signalquit);
   while (1)
   {
      //Something...
   }
   //Continue here after quit with "Control + C"
   return 0;
}

如何在while循环后和使用Control + C退出后返回主函数?谢谢你的回答!

1 个答案:

答案 0 :(得分:5)

  

如何通过信号留下无限循环?

标记你已完成。

#include <stdlib.h> /* for EXIT_XXX macros */
#include <signal.h>

volatile sig_atomic_t flag = 0;

void signalquit(int sig)
{
  flag = 1;

  signal(sig, SIG_DFL);

  return; /* Optional for void-functions */
}

int main(void)
{
  signal(SIGINT, signalquit);

  while (!flag)
  {
    //Something...
  }

  return EXIT_SUCCESS;
}

请注意,并非每个函数都可以从信号处理程序中调用。例如printf()不能保证async-signal-safe。

查找POSIX保证为异步信号安全scroll down here的函数列表。

您的代码使用signal()函数,由于历史原因,该函数非常难以移植。

便携式方法会使用function sigaction(),如下所示:

#include <stdlib.h> /* for EXIT_XXX macros */
#include <stdio.h> /* for perror() */
#include <signal.h>

volatile sig_atomic_t flag = 0;

int set_sig_handler(int sig, void(*handler)(int))
{
  struct sigaction sa = {0};
  sa.sa_handler = handler;
  return sigaction(sig, sa, NULL);
}

void signalquit(int sig)
{
  flag = 1;

  if (-1 == set_sig_handler(sig, SIG_DFL))
  {
    flag = 2;
  }
}

int main(void)
{
  if (-1 == set_sig_handler(SIGINT, signalquit))
  {
    perror("set_sig_handler() failed");
    return EXIT_FAILURE;
  }

  while (!flag)
  {
    //Something...
  }

  if (2 == flag)
  {
    perror("set_sig_handler() in signal handler failed");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<{> 3}} As pointed out更简单的方法是通过指定SA_RESETHAND标志显式安装处理程序以供单次使用。

#include <stdlib.h> /* for EXIT_XXX macros */
#include <stdio.h> /* for perror() */
#include <signal.h>

volatile sig_atomic_t flag = 0;

void signalquit(int sig)
{
  flag = 1;
}

int main(void)
{
  {
    struct sigaction sa = {0};

    sa.sa_handler = signalquit;
    sa.sa_flags = SA_RESETHAND;

    if (-1 == sigaction(SIGINT, sa, NULL))
    {
      perror("sigaction() failed");
      return EXIT_FAILURE;
    }
  }

  while (!flag)
  {
    //Something...
  }

  return EXIT_SUCCESS;
}