Use sigwait to block a specific signal without blocking SIGINT - c

I have a program that runs a loop, each time at the end of the loop, the process should sleep for some seconds(the number of seconds is not constant and is calculated at each loop) or until the process receives SIGINT, I used alarm() and sigwait() to do this but it's blocking the ctrl+c signal(i.e SIGINT) which I don't want, I want SIGINT to be received and acted upon normally, sample code below (note that somefunction() below is just an example, in the original code it does real calculation instead of using rand())
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
sigset_t sigs;
void setup_alarm()
{
printf("setting up signals\n");
sigemptyset(&sigs);
sigaddset(&sigs, SIGALRM);
sigprocmask(SIG_BLOCK, &sigs, NULL);
}
void wait_for_alarm(int interval)
{
printf("setting up alarm for %d seconds\n", interval);
alarm(interval);
printf("waiting for signal\n");
int sig_num = sigwait(&sigs, NULL);
// sigwaitinfo()
if (sig_num == 0)
{
printf("I received the alarm signal, breaking the wait\n");
}
else if (sig_num == EINVAL)
{
printf("some other error occurred");
perror("signal wait failed unexpectedly");
exit(1);
}
}
int somefunction()
{
srand(time(NULL));
return (rand() % 4) + 1;
}
int main(int argc, char *argv[])
{
int alarm_wait = 0;
setup_alarm();
while (1)
{
// do somework here
alarm_wait = somefunction();
// sleep for $alarm_wait or untill we receive SIGALARM
wait_for_alarm(alarm_wait);
}
return 0;
}
The results I'm getting is that when the execution reaches sigwait and I send the SIGINT signal(through ctrl-c) the program is not interrupted instead it keeps waiting until $alarm_wait has elapsed or until I send SIGALRM, what I want to do is have the logic only handles SIGALRM and every other signal should be handled normally(i.e SIGINT should interrupt the program even while it's waiting for SIGALRM signal)

Thanks to #Shawn for pointing out the second argument of sigwait I was able to solve my issue by also blocking SIGINT and using the second argument of sigwait to determine if the signal is SIGINT then execute exit(0)
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
sigset_t sigs;
void setup_alarm()
{
printf("setting up signals\n");
sigemptyset(&sigs);
sigaddset(&sigs, SIGALRM);
sigaddset(&sigs, SIGINT);
sigprocmask(SIG_BLOCK, &sigs, NULL);
}
void wait_for_alarm(int interval)
{
printf("setting up alarm for %d seconds\n", interval);
alarm(interval);
printf("waiting for signal\n");
int sig;
int sig_num = sigwait(&sigs, &sig);
if(sig == SIGINT)
exit(0);
if (sig_num == 0)
{
printf("I received the alarm signal, breaking the wait\n");
}
else if (sig_num == EINVAL)
{
printf("some other error occurred");
perror("signal wait failed unexpectedly");
exit(1);
}
}
int somefunction()
{
srand(time(NULL));
return (rand() % 4) + 1;
}
int main(int argc, char *argv[])
{
int alarm_wait = 0;
setup_alarm();
while (1)
{
// do somework here
alarm_wait = somefunction();
// sleep for $alarm_wait or untill we receive SIGALARM
wait_for_alarm(alarm_wait);
}
return 0;
}
The code now works as i would expect, i'm not sure if this is the best solution since i'm only handling two signals and don't know how the rest of the signals are being handled(maybe some of these signals are important for the init system for example).
I will leave my answer unaccepted for sometime incase someone has a better solution.

Related

Linux signal parent and child [c]

im new to Linux and im still learning my code job is simple it receives a signal from the parent and the child have to ignore the signal and print the number of the signal like [1,3,4,9,11], but my problem is the child does not print anything after the signal plus I want the child to ignore the signals especially like[sigquit] here is my code.
// C program to implement sighup(), sigint()
// and sigquit() signal functions
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
// function declaration
void sighup();
void sigint();
void sigquit();
void sigsegv();
// driver code
void main()
{
int pid;
/* get child process */
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { /* child */
signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
signal(SIGSEGV, sigsegv);
for (;;)
; /* loop for ever */
}
else /* parent */
{ /* pid hold id of child */
printf("\nPARENT: sending SIGHUP\n\n");
kill(pid, SIGHUP);
sleep(3); /* pause for 3 secs */
printf("\nPARENT: sending SIGINT\n\n");
kill(pid, SIGINT);
sleep(3); /* pause for 3 secs */
printf("\nPARENT: sending SIGQUIT\n\n");
kill(pid, SIGQUIT);
sleep(3);
}
}
// sighup() function definition
void sighup()
{
signal(SIGHUP, sighup); /* reset signal */
printf("CHILD: 1 [sighub]\n");
}
// sigint() function definition
void sigint()
{
signal(SIGINT, sigint); /* reset signal */
printf("CHILD: 2 [sigint]\n");
}
// sigsegv() function definition
void sigsegv()
{
signal(SIGSEGV, sigsegv); /* reset signal */
printf("CHILD: 11 [sigsegv]\n");
}
// sigquit() function definition
void sigquit()
{
signal(SIGINT, sigquit); /* reset signal */
printf("3 [sigquit]\n");
}
Check signal.h in /usr/bin/include, signal handler
/* Type of a signal handler. */
typedef void (*__sighandler_t) (int);
so need to change both the forward declaration and function definition to match this prototype as
// C program to implement sighup(), sigint()
// and sigquit() signal functions
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
// function declaration
void sighup(int);
void sigint(int);
void sigquit(int );
void sigsegv(int );
// driver code
int main()
{
int pid;
/* get child process */
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
if (pid == 0) { /* child */
signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
signal(SIGSEGV, sigsegv);
for (;;)
; /* loop for ever */
}
else /* parent */
{ /* pid hold id of child */
printf("\nPARENT: sending SIGHUP\n\n");
kill(pid, SIGHUP);
sleep(3); /* pause for 3 secs */
printf("\nPARENT: sending SIGINT\n\n");
kill(pid, SIGINT);
sleep(3); /* pause for 3 secs */
printf("\nPARENT: sending SIGQUIT\n\n");
kill(pid, SIGQUIT);
sleep(3);
}
return 0 ;
}
// sighup() function definition
void sighup(int signo)
{
signal(SIGHUP, sighup); /* reset signal */
printf("CHILD: 1 [sighub]\n");
}
// sigint() function definition
void sigint(int signo)
{
signal(SIGINT, sigint); /* reset signal */
printf("CHILD: 2 [sigint]\n");
}
// sigsegv() function definition
void sigsegv(int signo)
{
signal(SIGSEGV, sigsegv); /* reset signal */
printf("CHILD: 11 [sigsegv]\n");
}
// sigquit() function definition
void sigquit(int signo)
{
signal(SIGINT, sigquit); /* reset signal */
printf("3 [sigquit]\n");
}
As mentioned in comments, stdio functions like printf() aren't safe to use in signal handlers. On Linux, you should also use sigaction() instead of signal() to install signal handlers, as that avoids some issues with an imprecise definition of how handlers work in the latter function (Which should only be used when targeting bare bones standard C, not POSIX, where what signal handlers can do is even more restricted than in POSIX).
However, when targeting Linux or Unix platforms, you don't need signal handlers at all for this task! Each process has a signal mask, which controls which signals are blocked from having the normal execution of a handler or default action go off. If a process blocking signal X gets that signal, it's considered pending, and there are other ways to receive it. One such way in Linux is to use a signalfd, a special file descriptor that can be read from to get information about pending signals. An example using it:
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include <sys/wait.h>
int child_main(const sigset_t *, int);
void send_signals(pid_t, int *);
int main(void) {
// The signals we want to catch
int signals[] = {SIGHUP, SIGINT, SIGQUIT, SIGSEGV, -1};
// Set up the signal mask
sigset_t sigs, oldmask;
sigemptyset(&sigs);
for (int i = 0; signals[i] >= 0; i++) {
sigaddset(&sigs, signals[i]);
}
// To avoid a race condition where the parent starts sending signals
// before the child is ready for them, block the signals before
// forking the child
if (sigprocmask(SIG_BLOCK, &sigs, &oldmask) < 0) {
perror("sigprocmask");
return EXIT_FAILURE;
}
pid_t child = fork();
if (child < 0) {
perror("fork");
return EXIT_FAILURE;
} else if (child == 0) {
// In the child process
return child_main(&sigs, (sizeof signals / sizeof signals[0]) - 1);
} else {
// Parent process. Restore the original signal mask and send child signals
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
perror("parent sigprocmask");
kill(child, SIGKILL);
return EXIT_FAILURE;
}
send_signals(child, signals);
// Wait for the child to finish
if (waitpid(child, NULL, 0) < 0) {
perror("parent waitpid");
return EXIT_FAILURE;
}
}
return 0;
}
void send_signals(pid_t proc, int *signals) {
for (int i = 0; signals[i] >= 0; i++) {
printf("Sending process %d signal %s (%d)\n", (int)proc,
strsignal(signals[i]), signals[i]);
if (kill(proc, signals[i]) < 0) {
printf("Failed: %s\n", strerror(errno));
}
}
}
int child_main(const sigset_t *sigs, int nsigs) {
// Create a signalfd that monitors the given signals
int fd = signalfd(-1, sigs, 0);
if (fd < 0) {
perror("child signalfd");
return EXIT_FAILURE;
}
struct signalfd_siginfo s;
// Loop up to nsigs times reading from the signal fd
int count = 0;
while (++count <= nsigs && read(fd, &s, sizeof s) == sizeof s) {
printf("Child received signal %s (%d)\n", strsignal(s.ssi_signo),
s.ssi_signo);
}
if (count <= nsigs && errno != EINTR) {
perror("child read");
close(fd);
return EXIT_FAILURE;
}
close(fd);
return 0;
}
Example output:
Sending process 17248 signal Hangup (1)
Sending process 17248 signal Interrupt (2)
Sending process 17248 signal Quit (3)
Sending process 17248 signal Segmentation fault (11)
Child received signal Hangup (1)
Child received signal Segmentation fault (11)
Child received signal Interrupt (2)
Child received signal Quit (3)
Your program is running perfectly in my machine, so I don't understand why do you say the child doesn't print anything.
Anyway, you have to be careful, as the child is printing the messages of the received signals, but running forever, this means that when the parent is done and exit()s you leave a child running... forever? (and you are running the child without stopping or blocking, so consuming all the available cpu)
You must devise a method to kill such a process, because if you don't you will end with lots of processes running in your behalf, doing nothing but ignoring the kill()s you do to them.
For that, there are some signals that are not ignorable, the SIGKILL is one, you cannot install a signal handler to it, for security reasons... :)
Also, when using signal(2) system call, the handler is executed on the reception of the first signal, and switches to the default behaviour (which depends on the signal) when the signal handler is done.
If you want it to be permanent, you need to reinstall the signal handler (this has a race condition, in case you receive a second signal while you are executing the signal handler and have not had time to install it again) or call sigaction(2) instead, that allows you to permanently (while the process is running, or up to the next call you do to sigaction) install a signal handler that doesn't need to be renewed. Look at the manual page of sigaction, as you need to learn how to use it.

How to create a thread for signal handling and exit the process upon receiving the signal?

I written the below code to handle signals in separate thread to forcefully cleanup some resources and exit the complete process.
Here is the brief note about the below code.
When the signal is received, set volatile sig_atomic_t sig_set_flag = 1; inside signal handler.
In signal_handler_thread, checking sig_set_flag value in a loop.
if(sig_set_flag==1) send notifications like "i am going down" from signal_handler_thread and call exit(0); from the thread.
Signals can be received by any thread in a process. So i am setting the global variable.
I have 2 questions.
1) This implementation is fine? or i have to block the signals for the main thread and handle only by the spawned thread ?
2) How to block a signal to the main process and handle it in a thread?
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
/*
* Set this variable if any signal is received
*/
volatile sig_atomic_t sig_set_flag = 0;
pthread_mutex_t cleanup_mutex;
/*
* Resource cleanup function.
*/
int cleaup_resources() {
pthread_mutex_lock(&cleanup_mutex);
/*
* Send notification to all the clients.
* Delete all the temp files
*/
printf("Notified to clients.Exiting process\n");
pthread_mutex_unlock(&cleanup_mutex);
return 0;
}
/*
* Signal handler thread
*/
void sig_term_handler(int sig_num) {
sig_set_flag = sig_num;
}
/*
* Signal handler thread routine
*/
void *signal_handler_thread(void * args) {
while(1) {
if(sig_set_flag != 0) {
printf("%s : Signal flag is set for sig_no %d\n",__func__,sig_set_flag);
cleaup_resources();
break;
}
usleep(5);
}
exit(0);
}
int main()
{
int loop_count,status;
pthread_t tid;
pid_t pid;
struct sigaction sig;
sig.sa_handler = &sig_term_handler;
sig.sa_flags = 0;
sigaction(SIGTERM, &sig, NULL);
/*
* Spawn a thread to monitor signals.
* If signal received, Exit the process.
*/
pthread_create(&tid, NULL, signal_handler_thread, NULL);
while(1) {
printf("Some time consuming task in progress... PID = %d\n",getpid());
pid = fork();
if(pid == 0) {
sleep(100);
return 0;
} else {
waitpid(pid, &status, 0);
loop_count++;
if( loop_count>=10)
break;
}
}
cleaup_resources();
exit(0);
}
Note:I know signals will interrupt the some system calls and EINTR will be set. Unfortunately some system calls (i.e) waitpid() will not be interrupted. So i spawned a thread to handle this scenario.
1) Your implementation seems to be correct. signal() and sigaction() register a handler function for the whole process, so it doesn't matter you call them in the main thread or in the spawned thread.
2) To block a signal in the main thread, and handle it in a thread, you have to design, not a handler function, but a handler thread, using sigwait() or sigwaitinfo(). So the thread will wait for the signals and the program execution won't be interrupted.
In this case, you have to block process-wide signals in all the threads, including the main thread. If it is not blocked, the signal will have the default behavior on the program.
You have to use pthread_sigmask() to block one or more signals. An example of code to block SIGTERM:
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGTERM);
pthread_sigmask(SIG_BLOCK,&set,NULL);
When a thread is created, it inherits of the blocked signals of the creator thread.
I modified your code to show you how to use sigwaitinfo() and pthread_sigmask():
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
pthread_mutex_t cleanup_mutex;
/*
* Resource cleanup function.
*/
int cleaup_resources() {
pthread_mutex_lock(&cleanup_mutex);
/*
* Send notification to all the clients.
* Delete all the temp files
*/
printf("Notified to clients.Exiting process\n");
pthread_mutex_unlock(&cleanup_mutex);
return 0;
}
/*
* Signal handler thread routine
*/
void *signal_handler_thread(void * args) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGINT);
siginfo_t info;
while(1) {
sigwaitinfo(&set,&info);
if(info.si_signo == SIGINT){
printf("\nSIGINT received\n");
cleaup_resources();
exit(0);
}
}
}
int main()
{
int loop_count,status;
pthread_t tid;
pid_t pid;
sigset_t set;
sigemptyset(&set);
sigaddset(&set,SIGINT);
pthread_sigmask(SIG_BLOCK,&set,NULL);
// The new thread will inherit the blocked
// signals from the thread that create it:
pthread_create(&tid, NULL, signal_handler_thread, NULL);
while(1) {
printf("Some time consuming task in progress... PID = %d\n",getpid());
pid = fork();
if(pid == 0) {
sleep(100);
return 0;
} else {
waitpid(pid, &status, 0);
loop_count++;
if( loop_count>=10)
break;
}
}
cleaup_resources();
exit(0);
}
Also, be careful of the fork(), from the tests I have done, the child process will inherit of the blocked signals.

How to stop a child process if not completed after a timeout

I have a program that starts a child (r.out), and that child has a time limit.
I want to know how to stop running r.out after passing the time limit.
I am running the code on Linux.
This is what I have so far:
#include <unistd.h>
#include <signal.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#define TIME_LIMIT 1 //determine time limit
void my_function(); //supposed to include the submitted code
void alarm_handler(int);
int main()
{
if (sigaction(SIGALRM, NULL, NULL) == -1)
err(1, NULL);
signal(SIGALRM, alarm_handler); // assigning an alarm handler for SIGALRM
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
system("./r.out"); //Running the file
alarm(0);
return 0;
}
void alarm_handler(int sig)
{
printf("%s" , "Time limit exceeded");
//Here i want a code to stop the r.out file
}
In order to kill the child, you need to know its pid. You can get it if you start the program with fork and exec instead of system.
In addition to a signal handler for SIGALRM, set up one for SIGCHLD (received when a child process finishes) as well. After calling alarm to set the timer, call pause. This function will return when you get either of the two signals.
In the signal handlers you should only set a global flag. Calling printf from within a signal handler can lead to undefined behavior.
After pause returns, check each of the two flags. If the timeout flag is set, you can terminate the child with kill.
In either case, call wait to reap the child process's pid.
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TIME_LIMIT 1 //determine time limit
void alarm_handler(int);
void child_handler(int);
int timeout = 0;
int child_done = 0;
int main()
{
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
// child process
execl("./r.out","r.out", NULL);
perror("exec failed");
_exit(1);
}
// set up the signal handlers after forking so the child doesn't inherit them
signal(SIGALRM, alarm_handler);
signal(SIGCHLD, child_handler);
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
pause();
if (timeout) {
printf("alarm triggered\n");
int result = waitpid(pid, NULL, WNOHANG);
if (result == 0) {
// child still running, so kill it
printf("killing child\n");
kill(pid, 9);
wait(NULL);
} else {
printf("alarm triggered, but child finished normally\n");
}
} else if (child_done) {
printf("child finished normally\n");
wait(NULL);
}
return 0;
}
void child_handler(int sig)
{
child_done = 1;
}
void alarm_handler(int sig)
{
timeout = 1;
}

signal handler showing confusion in C

I am trying to use signal to sync N processes then print out something.
Each child process register a handler which print "yo" and "hihi" when catching SIGUSR1.
I use kill(0, SIGUSR1) to trigger every process. Since the default action for catching SIGUSR1 is being killed, I set a do-nothing handler for the main process so that it will wait all child died.
The fork and send signal program will repeat for k times, I expect it will show out N*k times "yo" and "hihi". However, it doesn't show enough "yo" and "hihi" as I expect. The number of "yo" is different every execution.
Here is my code, and thanks for your help!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#define N 3
int pid_id[N];
void handler2 (int signum)
{
printf("hihi\n");
}
void handler (int signum)
{
signal(SIGUSR2, handler2);
printf("yo\n");
raise(SIGUSR2);
}
void handler_do_nothing (int signum)
{
;
}
void child(int process_index)
{
struct sigaction sa;
/* Register */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sigaction(SIGUSR1, &sa, NULL);
printf("I am %d.\n", getpid());
pid_id[process_index] = getpid();
sleep(1);
exit(0);
}
int main()
{
int i, k, status;
pid_t pid[N];
pid_t pid_wait;
struct sigaction sa_main;
/* Register */ /* Main process will terminate if catch SIGUSR1 by default setting*/
memset(&sa_main, 0, sizeof(sa_main));
sa_main.sa_handler = handler_do_nothing;
sigaction(SIGUSR1, &sa_main, NULL);
/* Race k times */
for (k=0;k<3;k++)
{
for (i=0;i<N;i++)
{
pid[i] = fork();
if (pid[i]==0)
{
child(i);
}
}
// sleep();
kill(0, SIGUSR1);
for (i=0;i<N;i++)
{
do
{
pid_wait = waitpid(pid[i], &status, WNOHANG);
printf("I am waiting..\n");
sleep(1);
}while(pid_wait != pid[i]);
}
}
printf("all done\n");
return 0;
}
Your child processes are being signalled before they have had time (i.e. execution resource scheduled) to install the new signal handler.
This means that when the main program sends SIGUSR1, some subset of the child processes will still have handler_do_nothing installed.
If you want to wait until the child processes have all finished setting up, you will need to add some interprocess communication mechanism - e.g. the children could signal the parent process when they are ready.

Sending and handling a signal on a cloned thread

UPDATE: This appears to be a timing issue. Adding a call to sleep before the call to kill makes everything work as expected.
I have been playing with clone(2) and trying to get a handle on how it works. I am currently having trouble sending signals to a cloned process. I have the following code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <pthread.h>
volatile int keep_going = 1;
typedef void (*sighandler_t)(int);
void handler(int sig) {
printf("Signal Received\n");
keep_going = 0;
}
int thread_main(void* arg) {
struct sigaction usr_action;
sigset_t block_mask;
sigfillset(&block_mask);
usr_action.sa_handler = &handler;
usr_action.sa_mask = block_mask;
usr_action.sa_flags = 0;
sigaction(SIGUSR1, &usr_action, NULL);
printf("Hello from cloned thread\n");
while(keep_going);
}
int main(int argc, char **argv) {
void* stack = malloc(4096);
int flags = SIGCHLD;
int child_tid = clone(&thread_main, stack + 4096, flags, NULL);
if (child_tid < 0) {
perror("clone");
exit(EXIT_FAILURE);
}
printf("My pid: %d, child_tid: %d\n", (int) getpid(), (int) child_tid);
int kill_ret = kill(child_tid, SIGUSR1);
if (kill_ret < 0) {
perror("kill");
exit(EXIT_FAILURE);
}
int status = 0;
pid_t returned_pid = waitpid(child_tid, &status, 0);
if (returned_pid < 0) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
exit(EXIT_SUCCESS);
}
Which yields the following output:
My pid: 14101, child_tid: 14102
killed by signal 10
The child was obviously killed as a result of the signal, why did the signal handler not get called?
To avoid the race condition, catch the signal on the parent, before the clone() call. The child inherits a copy of the parent's signal handlers. You can reset it later on the parent to SIG_DFL if you want. (Also, getpid() is async-signal-safe, if you want to emulate SIG_DFL behaviour on the parent).
The child is not receiving the signal because before the child has reached to the call to sigaction the parent is sending the signal and thats why it is getting killed. You should avoid setting the signal handler this way. Still if you want to do this way only then make sure is parent is waiting until the child sets up the signal handler. With this scenario you should see the expected result.
First what is strange is you didn't get this message :
"Hello from cloned thread\n"
therefore your child tread gets terminated before it manages to setup the signal handler.
EDIT:
I just saw your comment about sleep. Try to add another variable, which is set when the sigaction gets executed. The main thread should be blocked until this variable is not set.

Resources