Reputation:
If I have something like this.
#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;
}
How can I return to my main function after the while loop and after quitting with Control + C? Thanks for your answers!
Upvotes: 2
Views: 177
Reputation: 70981
How to leave endless loop by signal?
By flagging that your are done.
#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;
}
Please note that not every function may be called from a signal handler. printf()
for example is not guaranteed to by async-signal-safe.
To find a list of functions to be guaranteed by POSIX to be async-signal-safe scroll down here.
Your code uses the signal()
function, which for historical reason is highly unportable.
A portable approach would use the function sigaction()
like for example below:
#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;
}
As pointed out by pilcrow an even simpler approach is to explicitly install the handler for single use only by specifying the SA_RESETHAND
flag.
#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;
}
Upvotes: 5