How to wake up a sleeping thread from the main Thread? - c

I have a capture program which in addition do capturing data and writing it into a file also prints some statistics.The function that prints the statistics
static void report(void)
{
/*Print statistics*/
}
is called roughly every second using an ALARM that expires every second.So The program is like
void capture_program()
{
pthread_t report_thread
while()
{
if(pthread_create(&report_thread,NULL,report,NULL)){
fprintf(stderr,"Error creating reporting thread! \n");
}
/*
Capturing code
--------------
--------------
*/
if(doreport)
/*wakeup the sleeping thread.*/
}
}
void *report(void *param)
{
//access some register from hardware
//sleep for a second
}
The expiry of the timer sets the doreport flag.If this flag is set report() is called which clears the flag.
How do I wake up the sleeping thread (that runs the report()) when the timer goes off in the main thread?

You can sleep a thread using sigwait, and then signal that thread to wake up with pthread_kill. Kill sounds bad, but it doesn't kill the thread, it sends a signal. This method is very fast. It was much faster than condition variables. I am not sure it is easier, harder, safer or more dangerous, but we needed the performance so we went this route.
in startup code somewhere:
sigemptyset(&fSigSet);
sigaddset(&fSigSet, SIGUSR1);
sigaddset(&fSigSet, SIGSEGV);
to sleep, the thread does this:
int nSig;
sigwait(&fSigSet, &nSig);
to wake up (done from any other thread)
pthread_kill(pThread, SIGUSR1);
or to wake up you could do this:
tgkill(nPid, nTid, SIGUSR1);
Our code calls this on the main thread before creating child threads. I'm not sure why this would be required.
pthread_sigmask(SIG_BLOCK, &fSigSet, NULL);

How do I wake up the sleeping thread (that runs the report()) when the
timer goes off in the main thread?
I think a condition variable is the mechanism you are looking for. Have the report-thread block on the condition variable, and the main thread signal the condition variable whenever you want the report-thread to wake up (see the link for more detailed instructions).

I had a similar issue when coding an UDP chat server: there is a thread_1 that only works when an alarm interruption (timeout to see if the client is still alive) OR another thread_2 (this thread meets client requests) signals arrives. What I did was put this thread_1 to sleep (sleep(n*TICK_TIMER), where TICK_TIMER is the alarm expiration value, n is some integer >1), and wake up this thread with SIGALRM signal. See sleep() doc
The alarm handler ( to use this you have to init it: "signal(SIGALRM, tick_handler); alarm(5);")
void tick_handler(){tick_flag++; alarm(5); }
will send a SIGALRM when timeout occurs.
And the command to wake this sleep thread_1 from another thread_2 is:
pthread_kill(X,SIGALRM);
where X is a pthread_t type. If your thread_1 is your main thread, you can get this number by pthread_t X = pthread_self();

Related

sleep() in thread causes main to sleep too

I have a gateway server and 2 clients.(made in Oracle VM VirtualBox).
In my gateway server, I have listener.c listening all packets.(in a while(1) loop).
If the client sends a valid token, I have to put it in my authorized MACs list and all packets coming from authorized MACs must be forwarded for 180 secs. (in other words, given internet access for 180 secs).
Before 180 sec., the thing with a single user it was working.
/* authorized MACs list */
char *auth_macs[5];
int client;
pthread_mutex_t lock;
/* after 3 min remove the client from auth list */
void *timer(void *arg){
sleep(180);
pthread_mutex_lock(&lock);
auth_macs[client] = " ";
client--;
pthread_mutex_unlock(&lock);
return NULL;
}
This is how I tried to implement my timer thread. client is a global variable that changes in main function.
if(has_token == 1){
client++;
sprintf(client_ip, "./accept.sh %s", sender);
system(client_ip);
auth_macs[client] = client_mac;
/* start timer thread */
pthread_t tid;
pthread_create(&tid, NULL, timer,NULL);
pthread_join(tid, NULL);
}
This is where I start this thread. accept.sh is a shell script to allow forwarding.
My problem is I thought sleep(180) in timer thread was only going to stop itself. But instead, listener.c stops receiving packets.
How can I fix this? I want timer to wait 180 secs but still be able to receive packets in main function.
sleep() only suspends the calling thread. So, it doesn't affect the main thread.
What's problematic is the pthread_join() call:
pthread_create(&tid, NULL, timer,NULL);
pthread_join(tid, NULL);
This effectively renders the multi-threading pointless. Because there's only thread that's ever going to make progress as the main thread waits until the created thread is completed.
You need to remove pthread_join() call and possibly it outside the while(1) loop if main thread needed to join. Alternatively, you can call pthread_exit(0) outside the thread creation loop so that main completes execution while the rest of the threads, if still alive when main thread
breaks its loop, can continue execution.

raise() of signal is not waking a sleeping process

I have a single thread program that sleeps to conserve battery power while waiting for hardware events. main() registers a signal handler, then sleeps. Hardware interrupt handlers may wake main by calling a function which calls raise(), and seeing any signal should wake main from sleep.
Now, for development purposes, I am running on a desktop, and instead of getting true hardware events, there are a couple of other processes which send fake hardware events. Instead of the interrupt handler making the aforementioned function calls, these tasks do.
A very simple demo case works fine, I can provide that code if needed, but don't want this post to be too long.
I have declared this signal handler:
void sig_handler( int signo )
{
//To confirm that this process is the same one that is sleeping
printf("sig_handler: my PID is %d\n", getpid());
if ( SIGUSR1 == signo)
{
printf("received SIGUSR1\n");
}
else
{
printf("received some other signal\n");
}
}
There is lot of other code, but the bit in question is that during init, I call:
sSigAction.sa_handler = sig_handler;
sigemptyset( &sSigAction.sa_mask );
sigaction( SIGUSR1, &sSigAction, NULL );
In a function called by another process (or interrupt handler in real system):
printf( "raising signal!\n");
raise( SIGUSR1 );
In main:
printf("main: my PID is %d\n", getpid());
while(1)
{
printf("sleeping forever\n");
usleep(-1);
printf("main is awake"\n);
//Do work we were waiting to do
}
The output looks like this:
main: my PID is 17250
sleeping forever
raising signal!
sig_handler: my PID is 17250
received SIGUSR1
Note the critical lack of "main is awake". As I said, doing these same steps does work, in a simple demo case. Since I am doing the same setup, I don't understand why it's not working. In both cases, I perform the same signal handler registration, usleep(), and raise(), but the demo case works and this does not.
Any ideas of what I could be missing?
Follow-up: I have found that if I use $kill -s USR1 then the task wakes as expected. So the mechanism is sound, but why does $kill work and raise() not?
Follow-up 2: I now have the function calling raise() also print getpid() and it matches the PID of main().
Resolution: While in the end I will have a single thread, and raise() would be appropriate right now I have multiple, and so must use kill(). It's that simple.

pthread_cond_signal from multiple threads

Let's imagine there is a thread which calls pthread_cond_wait and waits for signals:
pthread_mutex_lock(&m);
.....
while(run)
{
do {
pthread_cond_wait(&cond,&m);
} while(!got_signal);
got_signal = false;
do_something();
}
And there are multiple threads which are supposed to deliver signals:
pthread_mutex_lock(&m);
got_signal = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
Is this solution safe enough? What will happen if multiple threads send signals? Does m mutex suffice to guarantee all signals are serialized and won't be lost?
In the code you posted, the only place where threads are allowed to call pthread_cond_signal() is when they can acquire m, and that can only happen when your waiting thread is blocked on pthread_cond_wait().
However, it might happen that two signaling threads acquire the mutex after each other, before the waiting thread is woken up and can acquire the mutex. In that case you'll lose the second signal (and any further signals that might arrive after that, before the waiting thread runs), since your waiting thread can only "see" that it has been signaled, but not how many times this has happened.
To make sure that you don't lose any signals, you could use a counter instead of your got_signal flag:
Waiting thread:
pthread_mutex_lock(&m);
.....
while(run)
{
while(signal_count == 0) {
pthread_cond_wait(&cond,&m);
}
--signal_count;
do_something();
}
Signaling threads:
pthread_mutex_lock(&m);
++signal_count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);
(Also note that I've exchanged the do...whileloop with a while loop, to make sure that pthread_cond_wait() isn't called if there's still an unprocessed signal left.)
Now, if multiple threads end up signaling straight after each other, signal_count will become more than one, which will cause the waiting thread to run its do_something() multiple times instead of just once.

Blocking new signals while in handler

I have a parent process that manages a child (fork, execve). I created a handler in the parent to catch SIGCHLD signals from the child in order to call waitpid() and take appropriate action such as restarting the child.
I understood from the manual page for sigaction() that, while inside a signal handler, further signals of the same type would be blocked by default. I definitely wish for this behaviour so I decided to test it.
I put a sleep (my own implementation using clock_nanosleep() in a loop which resumes when interrupted) at the end of the signal handler and sent a SIGINT to the child. This duly made it quit and sent SIGCHLD to the parent. I logged the fact and started my sleep for 10 seconds. Now, I sent another SIGINT to the new child (sighandler restarted it first time) and was surprised to see another log and sleep happen.
How can this be? When I attached using a debugger to the parent it clearly showed two different threads interrupted to call my signal handler, both now sat in sleep. If that keeps up I will run out of threads!
I understand putting long sleeps into a signal handler is a daft thing to do but it does illustrate the point; I expected to see the second signal marked as pending in /proc/[PID]/status but instead it's delivered.
Here's the relevant bits of my code:
Set up the SIGCHLD handler:
typedef struct SigActType {
struct sigaction act;
int retval;
void (*func)(int);
}SigActType;
static SigActType sigActList[64];
public void setChildHandler(void (*func)(int)) {
SigActType *sat = &sigActList[SIGCHLD];
sat->act.sa_sigaction = sigchldHandler;
sigemptyset(&sat->act.sa_mask);
sigaddset (&sat->act.sa_mask, SIGTERM);
sigaddset (&sat->act.sa_mask, SIGINT);
sigaddset (&sat->act.sa_mask, SIGCHLD);
sat->act.sa_flags = SA_SIGINFO;
sat->retval = 0;
sat->func = func;
sigaction(SIGCHLD, &sat->act, NULL);
}
static void sigchldHandler(int sig, siginfo_t *si, void *thing) {
SigActType *sat = &sigActList[SIGCHLD];
if (sat->func) {
sat->func(si->si_pid);
}
}
and using this:
int main(int argc, char **argv) {
setChildHandler(manageChildSignals);
...
}
static void manageChildSignals(int d) {
if ((pid = waitpid(-1, &stat, WAIT_MYPGRP)) > 0) {
... restart child if appropriate
}
printf("start of pause...\n");
mySleep(10);
printf("end of pause...\n");
}
Stdout clearly shows:
(when I type kill -2 [PID]
start of pause
(when the new child is started and I type kill -2 [NEWPID]
start of pause
...10 seconds slide past...
end of pause
end of pause
I am puzzled as to why this happens. As you can see I even added SIGCHLD to the block mask for sigaction() to try to encourage it to do the right thing.
Any pointers most welcome!
signals of the same type would be blocked by default.
Yes, but only for the thread sigaction() is called from.
From man sigaction (bold emphasis by me):
sa_mask specifies a mask of signals which should be blocked (i.e.,
added to the signal mask of the thread in which the signal handler is
invoked) during execution of the signal handler.
As signal dispostion is per process any other thread not blocking the signal in question might receive it, that is get interupted and process it.
If this behaviour is not what you want you should perhaps modify the design of the way your program handles signals in such a way that per default all signals are blocked for each thread, and only one specifiy thread has signal reception unblocked.
Update:
Signals masks are inherited from the parent thread by the child thread.
If signal handling shall be done by one specific thread only, have the main thread block all signals prior to creating any other thread. Then create one specfic thread to do the signal handling, and have this thread unblock the signals to be handled. This concept also allows models like one thread per signal.
In a mutlithreaded environment use pthread_sigmask() to mask signals on a per thread base.
Please note that the behaviour of sigprocmask() in a multithreaded process is unspecified, use pthread_sigmask() then.

Linux Threads suspend/resume

I'm writing a code in which I have two threads running in parallel.
1st is the main thread which started the 2nd thread.
2nd thread is just a simple thread executing empty while loop.
Now I want to pause / suspend the execution of 2nd thread by 1st thread who created it.
And after some time I want to resume the execution of 2nd thread (by issuing some command or function) from where it was paused / suspended.
This question is not about how to use mutexes, but how to suspend a thread.
In Unix specification there is a thread function called pthread_suspend, and another called pthread_resume_np, but for some reason the people who make Linux, FreeBSD, NetBSD and so on have not implemented these functions.
So to understand it, the functions simply are not there. There are workarounds but unfortunately it is just not the same as calling SuspendThread on windows. You have to do all kinds of non-portable stuff to make a thread stop and start using signals.
Stopping and resuming threads is vital for debuggers and garbage collectors. For example, I have seen a version of Wine which is not able to properly implement the "SuspendThread" function. Thus any windows program using it will not work properly.
I thought that it was possible to do it properly using signals based on the fact that JVM uses this technique of signals for the Garbage collector, but I have also just seen some articles online where people are noticing deadlocks and so on with the JVM, sometimes unreproducable.
So to come around to answer the question, you cannot properly suspend and resume threads with Unix unless you have a nice Unix that implements pthread_suspend_np. Otherwise you are stuck with signals.
The big problem with Signals is when you have about five different libraries all linked in to the same program and all trying to use the same signals at the same time. For this reason I believe that you cannot actually use something like ValGrind and for example, the Boehm GC in one program. At least without major coding at the very lowest levels of userspace.
Another answer to this question could be. Do what Linuz Torvalds does to NVidia, flip the finger at him and get him to implement the two most critical parts missing from Linux. First, pthread_suspend, and second, a dirty bit on memory pages so that proper garbage collectors can be implemented. Start a large petition online and keep flipping that finger. Maybe by the time Windows 20 comes out, they will realise that Suspending and resuming threads, and having dirty bits is actually one of the fundamental reasons Windows and Mac are better than Linux, or any Unix that does not implement pthread_suspend and also a dirty bit on virtual pages, like VirtualAlloc does in Windows.
I do not live in hope. Actually for me I spent a number of years planning my future around building stuff for Linux but have abandoned hope as a reliable thing all seems to hinge on the availability of a dirty bit for virtual memory, and for suspending threads cleanly.
As far as I know you can't really just pause some other thread using pthreads. You have to have something in your 2nd thread that checks for times it should be paused using something like a condition variable. This is the standard way to do this sort of thing.
I tried suspending and resuming thread using signals, here is my solution. Please compile and link with -pthread.
Signal SIGUSR1 suspends the thread by calling pause() and SIGUSR2 resumes the thread.
From the man page of pause:
pause() causes the calling process (or thread) to sleep until a
signal is delivered that either terminates the process or causes the
invocation of a
signal-catching function.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
// Since I have only 2 threads so using two variables,
// array of bools will be more useful for `n` number of threads.
static int is_th1_ready = 0;
static int is_th2_ready = 0;
static void cb_sig(int signal)
{
switch(signal) {
case SIGUSR1:
pause();
break;
case SIGUSR2:
break;
}
}
static void *thread_job(void *t_id)
{
int i = 0;
struct sigaction act;
pthread_detach(pthread_self());
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_handler = cb_sig;
if (sigaction(SIGUSR1, &act, NULL) == -1)
printf("unable to handle siguser1\n");
if (sigaction(SIGUSR2, &act, NULL) == -1)
printf("unable to handle siguser2\n");
if (t_id == (void *)1)
is_th1_ready = 1;
if (t_id == (void *)2)
is_th2_ready = 1;
while (1) {
printf("thread id: %p, counter: %d\n", t_id, i++);
sleep(1);
}
return NULL;
}
int main()
{
int terminate = 0;
int user_input;
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, thread_job, (void *)1);
// Spawned thread2 just to make sure it isn't suspended/paused
// when thread1 received SIGUSR1/SIGUSR2 signal
pthread_create(&thread2, NULL, thread_job, (void *)2);
while (!is_th1_ready && !is_th2_ready);
while (!terminate) {
// to test, I am sensing signals depending on input from STDIN
printf("0: pause thread1, 1: resume thread1, -1: exit\n");
scanf("%d", &user_input);
switch(user_input) {
case -1:
printf("terminating\n");
terminate = 1;
break;
case 0:
printf("raising SIGUSR1 to thread1\n");
pthread_kill(thread1, SIGUSR1);
break;
case 1:
printf("raising SIGUSR2 to thread1\n");
pthread_kill(thread1, SIGUSR2);
break;
}
}
pthread_kill(thread1, SIGKILL);
pthread_kill(thread2, SIGKILL);
return 0;
}
There is no pthread_suspend(), pthread_resume() kind of APIs in POSIX.
Mostly condition variables can be used to control the execution of other threads.
The condition variable mechanism allows threads to suspend execution
and relinquish the processor until some condition is true. A condition
variable must always be associated with a mutex to avoid a race
condition created by one thread preparing to wait and another thread
which may signal the condition before the first thread actually waits
on it resulting in a deadlock.
For more info
Pthreads
Linux Tutorial Posix Threads
If you can use processes instead, you can send job control signals (SIGSTOP / SIGCONT) to the second process. If you still want to share the memory between those processes, you can use SysV shared memory (shmop, shmget, shmctl...).
Even though I haven't tried it myself, it might be possible to use the lower-level clone() syscall to spawn threads that don't share signals. With that, you might be able to send SIGSTOP and SIGCONT to the other thread.
For implementing the pause on a thread, you need to make it wait for some event to happen. Waiting on a spin-lock mutex is CPU cycle wasting. IMHO, this method should not be followed as the CPU cycles could have been used up by other processes/threads.
Wait on a non-blocking descriptor (pipe, socket or some other). Example code for using pipes for inter-thread communication can be seen here
Above solution is useful, if your second thread has more information from multiple sources than just the pause and resume signals. A top-level select/poll/epoll can be used on non-blocking descriptors. You can specify the wait time for select/poll/epoll system calls, and only that much micro-seconds worth of CPU cycles will be wasted.
I mention this solution with forward-thinking that your second thread will have more things or events to handle than just getting paused and resumed. Sorry if it is more detailed than what you asked.
Another simpler approach can be to have a shared boolean variable between these threads.
Main thread is the writer of the variable, 0 - signifies stop. 1 - signifies resume
Second thread only reads the value of the variable. To implement '0' state, use usleep for sime micro-seconds then again check the value. Assuming, few micro-seconds delay is acceptable in your design.
To implement '1' - check the value of the variable after doing certain number of operations.
Otherwise, you can also implement a signal for moving from '1' to '0' state.
You can use mutex to do that, pseudo code would be:
While (true) {
/* pause resume */
lock(my_lock); /* if this is locked by thread1, thread2 will wait until thread1 */
/* unlocks it */
unlock(my_lock); /* unlock so that next iteration thread2 could lock */
/* do actual work here */
}
You can suspend a thread simply by signal
pthread_mutex_t mutex;
static void thread_control_handler(int n, siginfo_t* siginfo, void* sigcontext) {
// wait time out
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
}
// suspend a thread for some time
void thread_suspend(int tid, int time) {
struct sigaction act;
struct sigaction oact;
memset(&act, 0, sizeof(act));
act.sa_sigaction = thread_control_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
sigemptyset(&act.sa_mask);
pthread_mutex_init(&mutex, 0);
if (!sigaction(SIGURG, &act, &oact)) {
pthread_mutex_lock(&mutex);
kill(tid, SIGURG);
sleep(time);
pthread_mutex_unlock(&mutex);
}
}
Not sure if you will like my answer or not. But you can achieve it this way.
If it is a separate process instead of a thread, I have a solution (This might even work for thread, maybe someone can share your thoughts) using signals.
There is no system currently in place to pause or resume the execution of the processes. But surely you can build one.
Steps I would do if I want it in my project:
Register a signal handler for the second process.
Inside the signal handler, wait for a semaphore.
Whenever you want to pause the other process, just send in a signal
that you registered the other process with. The program will go into
sleep state.
When you want to resume the process, you can send a different signal
again. Inside that signal handler, you will check if the semaphore is
locked or not. If it is locked, you will release the semaphore. So
the process 2 will continue its execution.
If you can implement this, please do share your feedack, if it worked for you or not. Thanks.

Resources