I am trying to have two timers in my system for two different purpose but I dont understand why it doesnt work. Can somebody help me?Also, Should the handler code be a bare minumum so the tasks themselves dont interfere with the tick? Also can I define separate handler?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <netinet/in.h>
#include <linux/socket.h>
#include <time.h>
#define SIGTIMER (SIGRTMAX)
#define SIG SIGUSR1
static timer_t tid;
static timer_t tid2;
void SignalHandler(int, siginfo_t*, void* );
timer_t SetTimer(int, int, int);
int main(int argc, char *argv[]) {
struct sigaction sigact;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_SIGINFO;
sigact.sa_sigaction = SignalHandler;
// set up sigaction to catch signal
if (sigaction(SIGTIMER, &sigact, NULL) == -1) {
perror("sigaction failed");
exit( EXIT_FAILURE );
}
// Establish a handler to catch CTRL+c and use it for exiting.
sigaction(SIGINT, &sigact, NULL);
tid=SetTimer(SIGTIMER, 1000, 1);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = SignalHandler;
// set up sigaction to catch signal
if (sigaction(SIG, &sa, NULL) == -1) {
perror("sa failed");
exit( EXIT_FAILURE );
}
// Establish a handler to catch CTRL+c and use it for exiting.
sigaction(SIGINT, &sa, NULL);
tid2=SetTimer(SIG, 1000, 3);
for(;;);
return 0;
}
void SignalHandler(int signo, siginfo_t* info, void* context)
{
if (signo == SIGTIMER) {
printf("Command Caller has ticked\n");
}else if (signo == SIG) {
printf("Data Caller has ticked\n");
} else if (signo == SIGINT) {
timer_delete(tid);
perror("Crtl+c cached!");
exit(1); // exit if CRTL/C is issued
}
}
timer_t SetTimer(int signo, int sec, int mode)
{
static struct sigevent sigev;
static timer_t tid;
static struct itimerspec itval;
static struct itimerspec oitval;
// Create the POSIX timer to generate signo
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = signo;
sigev.sigev_value.sival_ptr = &tid;
if (timer_create(CLOCK_REALTIME, &sigev, &tid) == 0) {
itval.it_value.tv_sec = sec / 1000;
itval.it_value.tv_nsec = (long)(sec % 1000) * (1000000L);
if (mode == 1) {
itval.it_interval.tv_sec = itval.it_value.tv_sec;
itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
}
else {
itval.it_interval.tv_sec = 0;
itval.it_interval.tv_nsec = 0;
}
if (timer_settime(tid, 0, &itval, &oitval) != 0) {
perror("time_settime error!");
}
}
else {
perror("timer_create error!");
return NULL;
}
return tid;
}
When you define your second timer with this tid2=SetTimer(SIG, 1000, 3);, your code configure this timer to be a one-shot-timer
if (mode == 1) {
itval.it_interval.tv_sec = itval.it_value.tv_sec; // here you arm the timer periodically (that's the meaning of it_interval
itval.it_interval.tv_nsec = itval.it_value.tv_nsec;
}
else {
itval.it_interval.tv_sec = 0; // here you arm the timer once
itval.it_interval.tv_nsec = 0;
}
If you configure the second timer with a mode=1, like this tid2=SetTimer(SIG, 1000, 4);, you'll obtain this on your console :
Command Caller has ticked
Data Caller has ticked
Command Caller has ticked
Data Caller has ticked
Command Caller has ticked
Data Caller has ticked
^CCrtl+c cached!: Success
And you can use different handlers for your timers because you're using different signals to catch their expiration.
Related
If I use the pthread_create() call in an infinite while loop in main, does it create multiple threads each time or will it only create the 2 threads that I need?
while(1){
pthread_create(&thread_1...);
pthread_create(&thread_2...);
}
it creates multiple threads each time.
you can use pthread_cancel to cancel any thread from the process.
Below is one of many ways to handle the termination of thread upon some event/timeout etc..
#include <stdio.h>
#include <signal.h> // for sigaction
#include <stdlib.h> // for exit and
#include <pthread.h> // for pthread
#include <string.h> // for memset
#define TIMEOUT 10
pthread_t tid1, tid2;
void* thread_function1(void *arg)
{
while(1)
{
printf(" thread_function1 invoked\n");
sleep(1); //avoid heavy prints
}
}
void* thread_function2(void *arg)
{
while(1)
{
printf(" thread_function2 invoked\n");
sleep(1); //avoid heavy prints
}
}
static void timer_handler(int sig, siginfo_t *siginfo, void *context)
{
printf("Inside handler function timeout happened \n");
if( sig == SIGALRM)
{
pthread_cancel(tid1);
pthread_cancel(tid2);
//exit(0); to exit from main
}
}
int main()
{
int count = 0;
void *status;
struct sigaction act;
memset (&act, '\0', sizeof(act));
sigemptyset(&act.sa_mask);
/* Use the sa_sigaction field because the handles has two additional parameters */
act.sa_sigaction = timer_handler;
/* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGALRM, &act, NULL) < 0)
{
perror ("sigaction SIGALRM");
return 1;
}
alarm (TIMEOUT);
pthread_create(&tid1,NULL,thread_function1,NULL);
pthread_create(&tid2,NULL,thread_function2,NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf(" MIAN ENDS ...BYE BYE \n");
return 0;
}
Subject says it all.
I want to be able to defer to the default OS signal handler for certain signals after I am done with my cleanups.
E.g. if SIGINT is received I want to terminate the program after my custom cleanup routine and want to make use of the standard OS routine for that instead of callind _exit() or whatever.
I figure I can get a reference to the original signal handler somehow before overwriting it with sigaction(), but i don't know how to do that.
This is the code I have at the moment:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
volatile sig_atomic_t sigterm_flag = 0;
volatile sig_atomic_t sighup_flag = 0;
volatile sig_atomic_t sig_default_flag = 0;
void sigact(int signum, siginfo_t *siginfo, void *ucontext)
{
switch(signum)
{
case SIGTERM:
sigterm_flag = 1;
break;
case SIGHUP:
sighup_flag = 1;
break;
default:
sig_default_flag = 1;
break;
}
}
int main(void)
{
struct sigaction sa;
sa.sa_sigaction = sigact;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
while (1) {
if (sigterm_flag == 1) {
sigterm_flag = 0;
printf("SIGTERM caught.\n");
}
if (sighup_flag == 1) {
sighup_flag = 0;
printf("SIGHUP caught.\n");
}
if (sig_default_flag == 1) {
sig_default_flag = 0;
printf("Other signal caught.\n");
}
sleep(1);
}
return 0;
}
EDIT:
Challenge solved based on suggestion from tuxlike in answer https://stackoverflow.com/a/64595945/8359654
Here is the final code:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
volatile sig_atomic_t sigterm_flag = 0;
volatile sig_atomic_t sighup_flag = 0;
volatile sig_atomic_t sigint_flag = 0;
volatile sig_atomic_t sig_default_flag = 0;
void sigact(int signum, siginfo_t *siginfo, void *ucontext)
{
switch(signum)
{
case SIGTERM:
sigterm_flag = 1;
break;
case SIGHUP:
sighup_flag = 1;
break;
case SIGINT:
sigint_flag = 1;
break;
default:
sig_default_flag = 1;
break;
}
}
int main(int argc, char *argv[])
{
struct sigaction sa;
struct sigaction sa_default;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = sigact;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa_default.sa_mask);
sa_default.sa_handler = SIG_DFL;
sa_default.sa_flags = 0;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
printf("Started %s as PID %ld\n", argv[0], (long int)getpid());
while (1) {
if (sigterm_flag == 1) {
sigterm_flag = 0;
printf("SIGTERM caught.\n");
}
if (sighup_flag == 1) {
sighup_flag = 0;
printf("SIGHUP caught.\n");
}
if (sigint_flag == 1) {
sigint_flag = 0;
printf("\nSIGINT caught.\n");
sigaction(SIGINT, &sa_default, NULL);
raise(SIGINT);
}
if (sig_default_flag == 1) {
sig_default_flag = 0;
printf("Other signal caught.\n");
}
sleep(1);
}
return 0;
}
(Note that you are missing sigemptyset(&sa.sa_mask); from your signal action structure initialization. It is a common, recommended practice to initially do a memset(&sa, 0, sizeof sa); to initialize all, even padding, to all-zeros, first.)
There is no userspace function for the default signal handler actions at all, the default handling happens in the kernel.
What you can do, is use sigaction() to reset the default action (sa.sa_handler = SIG_DFL; sa.sa_flags = 0;), then re-raise the signal using raise(signum), and return from the handler.
Both sigaction() and raise() are async-signal safe, and therefore perfectly acceptable to use in a signal handler.
Here i am trying achieve a timer say 0-10secs and an interval of 2secs each,so that i need to generate an interrupt # every 2secs(total 5 times) saying 2secs completed. which i have been cross checking in handler() function by using printf(). But i am not able to achieve the desired result.please put me touch if anyone is aware of it.
Thanks in advance.
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define SIGTIMER (SIGRTMAX)
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
void handler(int sig, siginfo_t *si, void *uc)
{
printf("Caught signal %d\n", sig);
}
int
main(int argc, char *argv[])
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
struct itimerspec oitval;
struct sigaction sa;
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIGTIMER);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGTIMER, &sa, NULL) == -1)
errExit("sigaction");
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGTIMER;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCK_REALTIME, &sev, &timerid) == 0)
{
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
its.it_value.tv_sec = 10;
its.it_value.tv_nsec =0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
if (timer_settime(timerid, 0, &its, &oitval) == -1)
errExit("timer_settime");
}
else
{
errExit("timer_create");
}
return 0;
}
First of all you should properly setup timeouts:
/* Start the timer */
its.it_value.tv_sec = 2;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 2;
its.it_interval.tv_nsec = 0;
it_value is the duration before first triggering, and it_interval is time between all subsequent triggerings. See here. Then, you shouldn't return from main() due it leads to process exit and you won't be able to observe timer ticks. You need to block execution somehow, e.g.
while(1) sleep(INT_MAX);
After each tick sleep() returns with errno set to EINTR so it should we wrapped into loop to allow timer to go ahead. Later you can decide when to leave this loop and exit.
P.S. Using printf() from signal handler is not a good idea. You should be very carefully with what you are doing there. It would be better just to write to some global variable and immediately return. And that var may be tested immediately after sleep() giving you an idea if you should sleep again or return.
I'm trying to implement interprocess communication by using POSIX signals in C, especially I'm writing Ping-Pong problem. So here's my source code:
#define CHILD 0
#define PARENT 1
int flag[2];
void handler(int sig) {
if (sig == SIGUSR1) {
flag[PARENT] = 1;
} else {
flag[CHILD] = 1;
}
return;
}
void child_process() {
while (1) {
printf("Ping!\n");
kill(getppid(), SIGUSR2);
while (flag[PARENT] == 0) { }
}
return;
}
void parent_process(pid_t t) {
while (1) {
//kill(t, SIGUSR1);
while (flag[CHILD] == 0) { }
printf("Pong!\n");
kill(t, SIGUSR1);
}
return;
}
void setup() {
flag[CHILD] = 0;
flag[PARENT] = 0;
signal(SIGUSR1, handler);
signal(SIGUSR2, handler);
}
int main(int argc, char* argv[]) {
setup();
pid_t t = fork();
if (t == 0) {
child_process();
} else {
parent_process(t);
}
return 0;
}
My program is not working properly, because sometimes I get "Pong!" "Pong!" "Pong!" or "Ping!" "Ping!" output. What's the problem?
And one more question, is my way of handling signals correct? Or there are more advanced ways to do it?
(1) Parent and child do not share the same memory. flag[CHILD] and flag[PARENT] will never know about each other because they are different copies in different processes.
(2) Yes, pretty much everything about your signal handling is wrong for what you are trying to do. You are trying to synchronize the signals so you need to use a mechanism that actually synchronizes them e.g. sigsuspend.
#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
void sig_hand(int sig) {}
sigset_t saveMask, blockMask;
void child_process()
{
int x = 0;
while(x < 10)
{
if (sigsuspend(&saveMask) == -1 && errno != EINTR)
errExit("sigsuspend");
printf("Pong %d!\n", ++x);
kill(getppid(), SIGUSR1);
}
return ;
}
void parent_process(pid_t pid)
{
int y = 0;
while (y < 10)
{
printf("Ping %d!\n", ++y);
kill(pid, SIGUSR1);
if (sigsuspend(&saveMask) == -1 && errno != EINTR)
errExit("sigsuspend");
}
return ;
}
int main(int argc, char* argv[])
{
//block SIGUSR1 in parent & child until ready to process it
sigemptyset(&blockMask);
sigaddset(&blockMask, SIGUSR1);
if (sigprocmask(SIG_BLOCK, &blockMask, &saveMask) == -1)
errExit("sigprocmask");
//set up signal handler for parent & child
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sig_hand;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
errExit("sigaction");
pid_t pid = fork();
if (pid == 0)
child_process();
else
parent_process(pid);
return 0;
}
Although it may not be your problem, remember anytime you are modifying variables asynchronous to program flow, you need to make those variables volatile so that the compilers does not optimize the accesses to them away.
I would think that semaphore.h has much more useful tools (sem_open, sem_post, sem_wait, sem_trywait).
I'd use the sigaction() and pause() functions, along with nanosleep() to rate-limit the activity.
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
enum { MAX_PINGS = 10 };
static sig_atomic_t sig_num;
static void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, ": (%d) %s", errnum, strerror(errnum));
putc('\n', stderr);
}
static void catcher(int sig)
{
sig_num = sig;
}
static void child_process(void)
{
struct timespec nap = { .tv_sec = 0, .tv_nsec = 100000000 };
while (1)
{
pause();
printf("Pong!\n");
nanosleep(&nap, 0);
kill(getppid(), SIGUSR1);
}
}
static void parent_process(pid_t pid)
{
struct timespec nap = { .tv_sec = 0, .tv_nsec = 100000000 };
for (int pings = 0; pings < MAX_PINGS; pings++)
{
printf("Ping %d!\n", pings);
nanosleep(&nap, 0);
kill(pid, SIGUSR1);
pause();
}
kill(pid, SIGTERM);
}
int main(void)
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = catcher;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
err_exit("Failed to set SIGUSR1 handler");
pid_t pid = fork();
if (pid < 0)
err_exit("Failed to fork()");
else if (pid == 0)
child_process();
else
parent_process(pid);
return 0;
}
The variable sig_num is there to quell complaints from the compiler about unused arguments (to the catcher function). The signal catcher is set before the fork(). The child process pauses until a signal arrives; then prints 'Pong!', takes a nap for 1/10 seconds, and then signals the parent process to wake. The parent process prints 'Ping!', takes a nap, signals the child process, and pauses until a signal arrives. It limits the loops to 10 (enough to show it is working), and when it is done, terminates the child before exiting.
Example output
$ ./pingpong
Ping 0!
Pong!
Ping 1!
Pong!
Ping 2!
Pong!
Ping 3!
Pong!
Ping 4!
Pong!
Ping 5!
Pong!
Ping 6!
Pong!
Ping 7!
Pong!
Ping 8!
Pong!
Ping 9!
Pong!
$
Clearly, it would not be hard to print a counter on the 'Pong' values too.
I'm trying to write a process in C/linux that ignores the SIGINT and SIGQUIT signals and exits for the SIGTERM. For the other signals it should write out the signal and the time. I'm having trouble cathing all the signals because i'm familiar only with catching 1 signal. If anyone could help me with this I'd appreciate it very much. Here is my code:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int done = 0;
void term(int signum)
{
if (signum == 15)
{
//printf("%d\n",signum);
printf("Received SIGTERM, exiting ... \n");
done = 1;
}
else
{
time_t mytime = time(0);
printf("%d: %s\n", signum, asctime(localtime(&mytime)));
printf("%d\n",signum);
}
}
int main(int argc, char *argv[])
{
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = term;
sigaction(SIGTERM, &action, NULL);
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = SIG_IGN;
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGINT, &act, NULL);
int loop = 0;
while(!done)
{
sleep(1);
}
printf("done.\n");
return 0;
}
Here is the easy way
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT\n");
}
int main(void)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
and so on.
signal() and sighandler() is the least complicated way to do this.
Call signal for each signal that you want to catch. But as some have said earlier you can only catch certain signals. Best to have a way to gracefully shut the program down.