Unable to reassign signal handler second time - c

I have a simple code which uses two signal handlers for "Segmentation fault" signal. First one works when signal happens and after longjmp, I do reassigning of handler with second one for that signal. Unfortunately, the flow of code doesn't reach necessary handler and I still get "Segmentation fault".
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
int i;
int ci;
jmp_buf m_env_buffer;
jmp_buf max_env_buffer;
void handler(int signum){
printf("sigsegv on i:[%d]", i);
ci = (++i);
longjmp(m_env_buffer,1);
}
void top_handler(int signum){
printf("sigsegv on max i:[%d]", i);
longjmp(max_env_buffer,10);
}
int main(void) {
signal(SIGSEGV, handler);
char * pstart = "loremipsum";
int m_cell = 0;
char m_cell_v;
int point;
point = setjmp(m_env_buffer);
if(point == 0){
for(i=0; ;i--){
m_cell_v = pstart[i];
}
}
//this wasn't invoked
signal(SIGSEGV, top_handler);
point = setjmp(max_env_buffer);
if(point == 0){
for(i=ci; ;i++){
char cur = pstart[i];
if(cur==10)
printf("\n");
printf("%c",cur);
}
}
puts("finish");
return 0;
}

signal() should not be used. It has unreliable semantics. On your system the default action (termination) is performed when the second SIGSEGV is received. The second call to signal() has effectively no effect.
You should use sigaction() instead. In your case you can use the following function instead of signal():
void set_signal (int signum, void (*handler)(int))
{
struct sigaction act;
act.sa_handler = handler;
sigemptyset (&act.sa_mask);
act.sa_flags = SA_NODEFER;
act.sa_restorer = NULL;
sigaction (signum, &act, NULL);
}
In the future, read the documentation at your disposal. A good ressource is the glibc manual. It has a good chapter on signal handling.

Related

Why the printf is never executing after an alarm?

I'm trying to do something simple with alarms, however the printf is never executing after I do the alarm, why's that?
#include <stdio.h>
#include <signal.h>
int main() {
alarm(3);
printf("Hello...\n");
alarm(6);
while(1);
printf("Hello2\n");
}
I want hello and hello2 to be printed, only hello is being printed for now
You didn't specify a handler for SIGALRM, and its default behavior (per man 7 signal) is to terminate the program. Even if you did specify a handler, after it ran, you'd still be in the while(1) loop.
Here's how you'd modify your program to fix both of those problems:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
volatile sig_atomic_t got_sigalrm = 0;
void handle_sigalrm(int signum) {
got_sigalrm = 1;
}
int main() {
struct sigaction act = { .sa_handler = handle_sigalrm };
sigaction(SIGALRM, &act, NULL);
alarm(3);
printf("Hello...\n");
alarm(6);
while(!got_sigalrm);
printf("Hello2\n");
}

C - Processes in linux handle with any signal

I'm writing code that have process who have to handle with any signal i gave him. I read that i should do something like that
void signalHandler(int sig_num)
{
// some stuff
}
//My process
int i;
for (i = 1; i <= 64; i++)
signal(i, signalHandler);
Is this correct solution ??
Although #Dylan's solution seems good and it is but it poses the a common problem and that is compatibility issue with signal function. It is hence recommended that you use sigaction always. Here is an example
#include <stdio.h>
#include <signal.h>
static void handler(int signo){
write(stdout, &signo, sizeof(int));
}
int main() {
struct sigaction sa;
sa.sa_handler = handler;
int i;
for (i = 1; i <= 64; i++) {
sigaction(i, &sa, NULL);
}
while(1);
return 0;
}
Try to avoid the use of signal as much as possible
Never use any function which are not Reentrant or not Async-signal-safe functions in signal handler like printf
Check the list of allowed functions in signal handler from here
POSIX.1-2004 (also known as POSIX.1-2001 Technical Corrigendum 2)
requires an implementation to guarantee that the following functions
can be safely called inside a signal handler:
You are on the right track if you want to handle signals 1 through 64 with the same signal handler. This test program will handle signals 1 through 64 by printing out its number.
#include <stdio.h>
#include <signal.h>
void signalHandler(int sig_num)
{
printf("Signal %d caught!\n", sig_num);
}
int main(int argc, char const *argv[])
{
//My process
int i;
for (i = 1; i <= 64; i++) {
signal(i, signalHandler);
}
while (1);
return 0;
}
For example, when you press CTRL+C while this program is running. The kernel sends signal 2 SIGINT to the program, and calls signalHandler(2). This program prints "Signal 2 caught!"
Post-Facepalm edit: this program obviously needs to be terminated with a kill -9 command........

signal's "siginfo_t* info" causes segmentation fault

I am making a program containing a "Server.c" which waits a client to send it a SIGUSR1 msg 10 times, then dies, and a "client.c" which sends a SIGUSR1 msg to the server.
The problem is that if I try to access the siginfo_t* info, I get a segmentation fault.
Note that this is being tested on a Debian ssh server on which I do not have high permissions.
Node that this code works fine on Ubuntu.
Can siginfo_t *info fail due to permission issues? Or is there another issue causing this portability problem. As far as I know libc should be fairly standard throughout any linux distro, possibly unix.
Any Ideas?
Thanks
server.c
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int counter = 0;
pid_t *clients = 0;
void on_signal(int signo, siginfo_t *info, void * context)
{
puts("SIGNAL RECEIVED");
assert(clients);
clients[counter] = info->si_pid;
++counter;
}
int main()
{
struct sigaction action;
sigset_t set;
int recieveflag = 0;
clients = (pid_t*)malloc(10 * sizeof(pid_t));
sigemptyset(&set);
sigaddset(&set, SA_SIGINFO);
memset(&action, 0, sizeof(struct sigaction));
action.sa_sigaction = on_signal;
sigaction(SIGUSR1, &action, 0);
while (counter < 10) {
//sigprocmask(SIG_BLOCK, &set, 0);
sigsuspend(&set);
}
puts("I'm done!");
return 0;
}
client.c:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int main(int argc, const char** argv)
{
int server_id;
assert(argc == 2);
server_id = atoi(argv[1]);
assert(server_id > 0);
kill(server_id, SIGUSR1);
return 0;
}
I tried editing server.c to:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int counter = 0;
pid_t *clients = 0;
void on_signal(int sig)
{
puts("SIGNAL RECEIVED");
}
int main()
{
struct sigaction action;
sigset_t set;
int recieveflag = 0;
clients = (pid_t*)malloc(10 * sizeof(pid_t));
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
memset(&action, 0, sizeof(struct sigaction));
action.sa_flags = SA_SIGINFO;
action.sa_handler = on_signal;
sigaction(SIGUSR1, &action, 0);
while (counter < 10) {
sigprocmask(SIG_BLOCK, &set, 0);
sigsuspend(&set);
++counter;
}
puts("I'm done!");
return 0;
}
now it no longer receives the SIGUSR1 event at all.
The basic behavior of sigaction is to call a simple callback like : void (*sa_handler)(int);. So if you want to use the sigaction handle with 3 parameters void (*sa_sigaction)(int, siginfo_t *, void *);, you must set the sa_flags field of your struct sigaction with the flag SA_SIGINFO. Take a look of the man page : http://www.kernel.org/doc/man-pages/online/pages/man2/sigaction.2.html who is clear.

Signal handler is not getting called in main function

I am trying to study how signal handlers work. I have written code where i cause an alarm signal to raise once in every 100us. But, the signal is not raised. Here is the code :
#include <signal.h>
#include <ucontext.h>
#include <sys/time.h>
#include<unistd.h>
#include<setjmp.h>
#include<stdio.h>
void handler(int signum, siginfo_t *ptr, ucontext_t *old_context)
{
printf("inside handler");
}
int main()
{
struct itimerval itv;
struct sigaction act;
act.sa_handler = handler;
act.sa_flags=SA_RESTART|SA_SIGINFO;
sigaction(SIGVTALRM, &act, 0);
itv.it_interval.tv_sec=0;
itv.it_interval.tv_usec=100;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 100;
setitimer(ITIMER_VIRTUAL, &itv, NULL); //engage timer
int i=0;
while(i<=100)
{
printf("main\n");
i++;
}
}
can some one explain what i am doing wrong?
Thanks
Your loop is probably taking less than 100us to run, try this:
volatile int i=0;
while(i<=100000000)
{
//printf("main\n");
i++;
}
I removed the printf so the output is not flooded, and made i volatile so the compiler won't optimize the loop.

Why thread function not invoking? ( SIGEV_THREAD )

I have a program where i invoke a signal sigkill(getpid(), SIGUSR1). I wish when the signal comes, instead of the signal handler the thread function should be invoked, or both.
For this i have populated the sigev_notify with SIGEV_THREAD.
But unfortunately, the thread function is not called. Why is it so?
Here is the code below:
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
static void ThreadhandlerTimer1(int);
void sig_handlerTimer1(int);
static void threadFunction(union sigval sv) // Should be invoked on receipt of signal "SIGEV_THREAD"
{
printf("Thread function invoked");
}
int main()
{
int i;
static struct sigaction sa;
static struct sigevent sevp;
memset (&sevp, 0, sizeof (struct sigevent));
sevp.sigev_value.sival_ptr = NULL;
sevp.sigev_notify = SIGEV_THREAD;
sevp.sigev_notify_attributes = NULL;
sevp.sigev_signo = SIGUSR1;
sevp.sigev_notify_function=threadFunction;
/* Setting the signal handlers */
sa.sa_handler = sig_handlerTimer1;
sa.sa_flags = 0;
sigaction(SIGUSR1, &sa, NULL);
for(i=0; i<10; i++)
{
if((i==3) || (i==6)){
kill(getpid(), SIGUSR1);
}
printf("%d\n",i);
sleep(1);
}
}
void sig_handlerTimer1(int signum)
{
printf("Caught signal: %d\n",signum);
}
According to this documentation, the sigevent structure is only supported by "Some signal-generating functions, such as high-resolution timer expiration, asynchronous I/O completion, interprocess message arrival, and the sigqueue() function."
I don't know what your real plan for this code is (maybe you can tell us), but as it is, you are raising the signal directly which probably is not one of the supported cases for using SIGEV. If this code is fairly close to what you want in production you could simply call sigqueue() instead of kill() and it may just work.
From your code, it seems you have just assigned values to sigevent, instead of using any where in code.
static struct sigevent sevp;
memset (&sevp, 0, sizeof (struct sigevent));
sevp.sigev_value.sival_ptr = NULL;
sevp.sigev_notify = SIGEV_THREAD;
sevp.sigev_notify_attributes = NULL;
sevp.sigev_signo = SIGUSR1;
sevp.sigev_notify_function=threadFunction;
To invoke threadFunction, call this from your signal handler.
> void sig_handlerTimer1(int signum)
> {
> printf("Caught signal: %d\n",signum);
> threadFunction(signum);
> }
If you want to use sevp, use something like timer_create() and timer_settime().
Check this link:
http://ptgmedia.pearsoncmg.com/images/0201633922/sourcecode/sigev_thread.c

Resources