SIGINT signal()/sigaction in C++ - c++

So here is my code:
void sigHandle(int sig)
{
signal(SIGINT, sigHandle); //Is this line necessairy?
cout<<"Signal: "<<sig<<endl;
}
int main(){
signal(SIGINT, sigHandle);
while(true){ //Supposed to loop until user exits.
//rest of my code
}
}
Now it is my understanding of signal() that when the SIGINT command (Ctrl+C right?) is received my function sigHandle should be called with an integer value of 2 (the SIGINT number), the method should run and the program should NOT exit.
All I would like to do is just print the signal number and move on, however after printing out "Signal: 2" it exits.
(Eventually I'm supposed to handle the first 32 interrupts but I figured Ctrl+C would be the most difficult so I'm starting here.)
In main if I do signal(SIGINT, SIG_IGN); it ignores the signal correctly and doesn't exit but I now have no way of knowing if I recieved the SIGINT interrupt.
Earlier I was playing around with the sigaction struct but I could not find any real comprehensive documentation on it so I decided to go with just "raw" signal handling.
This was my sigaction code (same problem as above):
struct sigaction action;
action.sa_handler = sigHandle;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
sigaction(SIGINT, &action, 0);
Thanks for your help!
EDIT
OK SO After many many many hours of scowering through man pages and the internet I have happened across a (very) ghetto solution involving saving the stack pre-infinite loop then when the interrupt comes, doing what I need to do, then re-setting the stack back to where it was and calling the sigrelse() command to re-set any states that might have been changed and not re-loaded.
I understand that this is not the most elegant/efficient/or even socially acceptable solution to this problem but it works and as far as I can tell I am not leaking any memory anywhere so it's all good...
I am still looking for a solution to this problem and I view my stack re-setting shenanigins as only a temporary fix...
Thanks!

Also note you should not call stdio (or other non-reentrant functions) in signal handlers.
(your signal handler might be invoked in the middle of a malloc or it's C++ equivalent)

It is not. You just replacing SIGINT's handles with same function. How does you program perform wait?
If you have something like:
int main
{
// ...
int r = read(fd, &buff, read_size); // your program hangs here, waiting for the data.
// but if signal occurred during this period of time
// read will return immediately, and r may != read_size
return 0; // then it will go straight to return.
}

Related

Signal Handling (c++)

I have this simple code that loops the word "SIGNALS ARE COOL" I'm trying to make it take signals like (SIGFPE. SIGABRT, SIGINT, SIGSEGV.) and show the signal type and the time I made this code that takes "SIGINT" signal how do I add more signals and how to control what my program show when the signals are triggered by the user.
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <csignal>
using namespace std;
void signalHandler(int signum) {
cout << "Interrupt signal (" << signum << ") received.\n";
// cleanup and close up stuff here
// terminate program
exit(signum);
}
int main() {
// register signal SIGINT and signal handler
signal(SIGINT, signalHandler);
while (1) {
cout << "SIGNALS ARE COOL" << endl;
}
return 0;
}
I see that this looks like an assignment; so what I'm saying may not be relevant to you (but might be to someone someday).
--EDIT--
I see you've also got stdafx.h, which I think is a Visual Studio Windows thing, and here I am suggesting a POSIX solution (not pure C++). I didn't read carefully enough, and that invalidates my whole answer (I think). You probably can't use my suggestion, and for that I'm sorry.
However, I'm going to leave it here in case someone one day finds this and needs to work with signals in a Unix system.
--
I've found that it's often a lot more practical to avoid signal handling functions like this altogether, and take signals on your own terms. As noted by others, there's a lot of rules about what you can and can't do within a signal handler, because they can be invoked at any time, in any thread, unless you take extra precautions. I've seen this result in a lot of messy code, things like 'have a global bool got_signal that gets checked by things all over the application to know if they're supposed to shut down'. There's obviously nice ways to do signal handling, but at this point I try to avoid it altogether in favor of other options.
The functions pthread_sigmask and sigwait can be used to invert control here and allow you to accept signals within the defined flow of program execution where you want it, and then you don't need to worry about taking invalid actions when you handle them. Using pthread_sigmask you can tell the OS not to interrupt your program to deliver signals and instead queue them up, and then sigwait can be used to handle them at an appropriate time. You can't do this with all signals (some things like kill -9 and a SEGFAULT can't/shouldn't be ignored), but it works well for most of them.
Using an approach like this, it's really easy to interact with signals in a larger application too. You can block signals at the start of main, and that will propagate to all children threads, and then you can designate one specific child thread to just wait for signals an pass events into the rest of the application in whatever method is appropriate for the framework of your application.
#include <signal.h>
#include <unistd.h>
#include <initializer_list>
#include <functional>
#include <algorithm>
#include <iostream>
sigset_t make_sigset(std::initializer_list<int32_t> signals)
{
sigset_t set;
const int32_t result = sigemptyset(&set);
std::for_each(signals.begin(), signals.end(), std::bind(&sigaddset, &set, std::placeholders::_1));
return set;
}
int main()
{
const auto signal_list = make_sigset({SIGTERM, SIGSEGV, SIGINT, SIGABRT});
pthread_sigmask(SIG_BLOCK, &signal_list, nullptr);
int32_t last_signal;
do
{
sigwait(&signal_list, &last_signal);
std::cout << "Got signal " << last_signal << std::endl;
// Exit on sigint so ctrl+c still works
} while (last_signal != SIGINT);
return 0;
}
As already mentioned by #Eljay in the comments, you have to be careful with the things you do in a signal handler.
I'd also suggest not using namespace std, but that's a story for another time link.
I'd recommend you this page which explains a lot about what signals can and cannot do, according to the c++ standard. Now what they actually do in your compiler (which I assume is MSVC) may be different.
Some of the important bits, as already mentioned, you shouldn't do I/O, you shouldn't throw, etc...
To answer your question, you were on the right track, adding other signals can be done via:
// catch SIGTERM
std::signal(SIGTERM, signalHandler);
std::signal(SIGSEGV, signalHandler);
std::signal(SIGINT, signalHandler);
std::signal(SIGABRT, signalHandler);
// insert others
Then, what I'd suggest is storing the value of your signal into some atomic variable, like: gSignalThatStoppedMe.
std::atomic<int> gSignalThatStoppedMe = -1;
// I also added 'extern "C"' because the standard says so
extern "C" void signalHandler(int signum) {
gSignalThatStoppedMe.store(signum);
}
Then, your while loop would check for != -1, or pick another value for this, I've not checked if some implementations use -1 as a valid value for signals
// ...
while(gSignalThatStoppedMe.load() == -1)
{
// your old code
}
Now, do a switch of sorts, with the values inside and output the signal that stopped it, something like:
switch(gSignalThatStoppedMe.load())
{
case SIGINT:
std::puts("It was SIGINT");
break;
case SIGTERM:
std::puts("It was SIGTERM");
break;
default:
break;
}
I think this has less undefined behavior, which is always a good thing.
EDIT: here's a compiler explorer link
The output with CTRL-C:
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
SIGNALS ARE COOL
Interrupt signal SIGINT (2) received.

How can I make poll() exit immediately in C on Linux?

I'm using the function poll() (I think it might be part of POSIX?) C function in my C++ class in order to get an event when a file changes. This seems to work just fine - but now I also want to be able to cause the function to exit immediately when I need to close the thread.
I researched this and came up with a couple of ideas that I tried - like trying to send a signal, but I couldn't figure out how to get this to work.
In the code below (which isn't 100% complete, but should have enough to illustrate the problem), I have a C++ class that starts a thread from the constructor and wants to clean up that thread in the destructor. The thread calls poll() which returns when the file changes, and then it informs the delegate object. The monitoring thread loops until the FileMonitor object indicates it can quit (using a method that returns a bool).
In the destructor, what I would like to do is flip the bool, then do something that causes poll() to exit immediately, and then call *pthread_join()*. So, any ideas on how I can make poll() exit immediately?
This code is targeted towards Linux (specifically debian), but I'm also working on it on a Mac. Ideally it the poll() API should work basically the same.
void * manage_fm(void *arg)
{
FileMonitor * theFileMonitor = (FileMonitor*)arg;
FileMonitorDelegate * delegate;
unsigned char c;
int fd = open(theFileMonitor->filepath2monitor(), O_RDWR);
int count;
ioctl(fd, FIONREAD, &count);
for (int i=0;i<count;++i) {
read(fd, &c, 1);
}
struct pollfd poller;
poller.fd = fd;
poller.events = POLLPRI;
while (theFileMonitor->continue_managing_thread()) {
delegate = theFileMonitor->delegate;
if (poll(&poller, 1, -1) > 0) {
(void) read(fd, &c, 1);
if (delegate) {
delegate->fileChanged();
}
}
}
}
FileMonitor::FileMonitor( )
{
pthread_mutex_init(&mon_mutex, NULL);
manage_thread = true;
pthread_mutex_lock (&mon_mutex);
pthread_create(&thread_id, NULL, manage_fm, this);
pthread_mutex_unlock(&pin_mutex);
}
FileMonitor::~FileMonitor()
{
manage_thread = false;
// I would like to do something here to force the "poll" function to return immediately.
pthread_join(thread_id, NULL);
}
bool FileMonitor::continue_managing_thread()
{
return manage_thread;
}
const char * FileMonitor::filepath2monitor()
{
return "/some/example/file";
}
Add a pipe to your file monitor class and switch your poll to take both your original file descriptor and the pipe's read descriptor to poll on. When you want to wake up your file monitor class for it to check for exit, send a byte through the pipe's write descriptor, that will wake up your thread.
If you have a large number of these file monitors, there's the possibility you could hit the maximum number of file descriptors for a process (See Check the open FD limit for a given process in Linux for details, on my system it's 1024 soft, 4096 hard). You could have multiple monitor classes share a single pipe if you don't mind them all waking up at once to check their exit indicator.
You should use a pthread condition variable inside (and just before) the poll-ing loop, and have the other thread calling pthread_cond_signal
You might consider the pipe(7) to self trick (e.g. have one thread write(2) a byte -perhaps just before pthread_cond_signal- to a pipe poll(2)-ed by another thread who would read(2) the same pipe). See also signal-safety(7) and calling Qt functions from Unix signal handlers. Both could inspire you.
With that pipe-to-self trick, assuming you do poll for reading that pipe, the poll will return. Of course some other thread would have done a write on the same pipe before.
See also Philippe Chaintreuil's answer, he suggests a similar idea.

set flag in signal handler

In C++11, what is the safest (and perferrably most efficient) way to execute unsafe code on a signal being caught, given a type of request-loop (as part of a web request loop)? For example, on catching a SIGUSR1 from a linux command line: kill -30 <process pid>
It is acceptable for the 'unsafe code' to be run on the next request being fired, and no information is lost if the signal is fired multiple times before the unsafe code is run.
For example, my current code is:
static bool globalFlag = false;
void signalHandler(int sig_num, siginfo_t * info, void * context) {
globalFlag = true;
}
void doUnsafeThings() {
// thigns like std::vector push_back, new char[1024], set global vars, etc.
}
void doRegularThings() {
// read filesystem, read global variables, etc.
}
void main(void) {
// set up signal handler (for SIGUSR1) ...
struct sigaction sigact;
sigact.sa_sigaction = onSyncSignal;
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction(SIGUSR1, &sigact, (struct sigaction *)NULL);
// main loop ...
while(acceptMoreRequests()) { // blocks until new request received
if (globalFlag) {
globalFlag = false;
doUnsafeThings();
}
doRegularThings();
}
}
where I know there could be problems in the main loop testing+setting the globalFlag boolean.
Edit: The if (globalFlag) test will be run in a fairly tight loop, and an 'occasional' false negative is acceptable. However, I suspect there's no optimisation over Basile Starynkevitch's solution anyway?
You should declare your flag
static volatile sig_atomic_t globalFlag = 0;
See e.g. sig_atomic_t, this question and don't forget the volatile qualifier. (It may have been spelled sigatomic_t for C).
On Linux (specifically) you could use signalfd(2) to get a filedescriptor for the signal, and that fd can be poll(2)-ed by your event loop.
Some event loop libraries (libevent, libev ...) know how to handle signals.
And there is also the trick of setting up a pipe (see pipe(2) and pipe(7) for more) at initialization, and just write(2)-ing some byte on it in the signal handler. The event loop would poll and read that pipe. Such a trick is recommended by Qt.
Read also signal(7) and signal-safety(7) (it explains what are the limited set of functions or syscalls usable inside a signal handler)....
BTW, correctness is more important than efficiency. In general, you get few signals (e.g. most programs get a signal once every second at most, not every millisecond).

How to pause a pthread ANY TIME I want?

recently I set out to port ucos-ii to Ubuntu PC.
As we know, it's not possible to simulate the "process" in the ucos-ii by simply adding a flag in "while" loop in the pthread's call-back function to perform pause and resume(like the solution below). Because the "process" in ucos-ii can be paused or resumed at any time!
How to sleep or pause a PThread in c on Linux
I have found one solution on the web-site below, but it can't be built because it's out of date. It uses the process in Linux to simulate the task(acts like the process in our Linux) in ucos-ii.
http://www2.hs-esslingen.de/~zimmerma/software/index_uk.html
If pthread can act like the process which can be paused and resumed at any time, please tell me some related functions, I can figure it out myself. If it can't, I think I should focus on the older solution. Thanks a lot.
The Modula-3 garbage collector needs to suspend pthreads at an arbitrary time, not just when they are waiting on a condition variable or mutex. It does it by registering a (Unix) signal handler that suspends the thread and then using pthread_kill to send a signal to the target thread. I think it works (it has been reliable for others but I'm debugging an issue with it right now...) It's a bit kludgy, though....
Google for ThreadPThread.m3 and look at the routines "StopWorld" and "StartWorld". Handler itself is in ThreadPThreadC.c.
If stopping at specific points with a condition variable is insufficient, then you can't do this with pthreads. The pthread interface does not include suspend/resume functionality.
See, for example, answer E.4 here:
The POSIX standard provides no mechanism by which a thread A can suspend the execution of another thread B, without cooperation from B. The only way to implement a suspend/restart mechanism is to have B check periodically some global variable for a suspend request and then suspend itself on a condition variable, which another thread can signal later to restart B.
That FAQ answer goes on to describe a couple of non-standard ways of doing it, one in Solaris and one in LinuxThreads (which is now obsolete; do not confuse it with current threading on Linux); neither of those apply to your situation.
On Linux you can probably setup custom signal handler (eg. using signal()) that will contain wait for another signal (eg. using sigsuspend()). You then send the signals using pthread_kill() or tgkill(). It is important to use so-called "realtime signals" for this, because normal signals like SIGUSR1 and SIGUSR2 don't get queued, which means that they can get lost under high load conditions. You send a signal several times, but it gets received only once, because before while signal handler is running, new signals of the same kind are ignored. So if you have concurent threads doing PAUSE/RESUME , you can loose RESUME event and cause deadlock. On the other hand, the pending realtime signals (like SIGRTMIN+1 and SIGRTMIN+2) are not deduplicated, so there can be several same rt signals in queue at the same time.
DISCLAIMER: I had not tried this yet. But in theory it should work.
Also see man 7 signal-safety. There is a list of calls that you can safely call in signal handlers. Fortunately sigsuspend() seems to be one of them.
UPDATE: I have working code right here:
//Filename: pthread_pause.c
//Author: Tomas 'Harvie' Mudrunka 2021
//Build: CFLAGS=-lpthread make pthread_pause; ./pthread_pause
//Test: valgrind --tool=helgrind ./pthread_pause
//I've wrote this code as excercise to solve following stack overflow question:
// https://stackoverflow.com/questions/9397068/how-to-pause-a-pthread-any-time-i-want/68119116#68119116
#define _GNU_SOURCE //pthread_yield() needs this
#include <signal.h>
#include <pthread.h>
//#include <pthread_extra.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <sys/resource.h>
#include <time.h>
#define PTHREAD_XSIG_STOP (SIGRTMIN+0)
#define PTHREAD_XSIG_CONT (SIGRTMIN+1)
#define PTHREAD_XSIGRTMIN (SIGRTMIN+2) //First unused RT signal
pthread_t main_thread;
sem_t pthread_pause_sem;
pthread_once_t pthread_pause_once_ctrl = PTHREAD_ONCE_INIT;
void pthread_pause_once(void) {
sem_init(&pthread_pause_sem, 0, 1);
}
#define pthread_pause_init() (pthread_once(&pthread_pause_once_ctrl, &pthread_pause_once))
#define NSEC_PER_SEC (1000*1000*1000)
// timespec_normalise() from https://github.com/solemnwarning/timespec/
struct timespec timespec_normalise(struct timespec ts)
{
while(ts.tv_nsec >= NSEC_PER_SEC) {
++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC;
}
while(ts.tv_nsec <= -NSEC_PER_SEC) {
--(ts.tv_sec); ts.tv_nsec += NSEC_PER_SEC;
}
if(ts.tv_nsec < 0) { // Negative nanoseconds isn't valid according to POSIX.
--(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec);
}
return ts;
}
void pthread_nanosleep(struct timespec t) {
//Sleep calls on Linux get interrupted by signals, causing premature wake
//Pthread (un)pause is built using signals
//Therefore we need self-restarting sleep implementation
//IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart
//We also need to sleep using absolute time, because relative time is paused
//You should use this in any thread that gets (un)paused
struct timespec wake;
clock_gettime(CLOCK_MONOTONIC, &wake);
t = timespec_normalise(t);
wake.tv_sec += t.tv_sec;
wake.tv_nsec += t.tv_nsec;
wake = timespec_normalise(wake);
while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break;
return;
}
void pthread_nsleep(time_t s, long ns) {
struct timespec t;
t.tv_sec = s;
t.tv_nsec = ns;
pthread_nanosleep(t);
}
void pthread_sleep(time_t s) {
pthread_nsleep(s, 0);
}
void pthread_pause_yield() {
//Call this to give other threads chance to run
//Wait until last (un)pause action gets finished
sem_wait(&pthread_pause_sem);
sem_post(&pthread_pause_sem);
//usleep(0);
//nanosleep(&((const struct timespec){.tv_sec=0,.tv_nsec=1}), NULL);
//pthread_nsleep(0,1); //pthread_yield() is not enough, so we use sleep
pthread_yield();
}
void pthread_pause_handler(int signal) {
//Do nothing when there are more signals pending (to cleanup the queue)
//This is no longer needed, since we use semaphore to limit pending signals
/*
sigset_t pending;
sigpending(&pending);
if(sigismember(&pending, PTHREAD_XSIG_STOP)) return;
if(sigismember(&pending, PTHREAD_XSIG_CONT)) return;
*/
//Post semaphore to confirm that signal is handled
sem_post(&pthread_pause_sem);
//Suspend if needed
if(signal == PTHREAD_XSIG_STOP) {
sigset_t sigset;
sigfillset(&sigset);
sigdelset(&sigset, PTHREAD_XSIG_STOP);
sigdelset(&sigset, PTHREAD_XSIG_CONT);
sigsuspend(&sigset); //Wait for next signal
} else return;
}
void pthread_pause_enable() {
//Having signal queue too deep might not be necessary
//It can be limited using RLIMIT_SIGPENDING
//You can get runtime SigQ stats using following command:
//grep -i sig /proc/$(pgrep binary)/status
//This is no longer needed, since we use semaphores
//struct rlimit sigq = {.rlim_cur = 32, .rlim_max=32};
//setrlimit(RLIMIT_SIGPENDING, &sigq);
pthread_pause_init();
//Prepare sigset
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, PTHREAD_XSIG_STOP);
sigaddset(&sigset, PTHREAD_XSIG_CONT);
//Register signal handlers
//signal(PTHREAD_XSIG_STOP, pthread_pause_handler);
//signal(PTHREAD_XSIG_CONT, pthread_pause_handler);
//We now use sigaction() instead of signal(), because it supports SA_RESTART
const struct sigaction pause_sa = {
.sa_handler = pthread_pause_handler,
.sa_mask = sigset,
.sa_flags = SA_RESTART,
.sa_restorer = NULL
};
sigaction(PTHREAD_XSIG_STOP, &pause_sa, NULL);
sigaction(PTHREAD_XSIG_CONT, &pause_sa, NULL);
//UnBlock signals
pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
}
void pthread_pause_disable() {
//This is important for when you want to do some signal unsafe stuff
//Eg.: locking mutex, calling printf() which has internal mutex, etc...
//After unlocking mutex, you can enable pause again.
pthread_pause_init();
//Make sure all signals are dispatched before we block them
sem_wait(&pthread_pause_sem);
//Block signals
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, PTHREAD_XSIG_STOP);
sigaddset(&sigset, PTHREAD_XSIG_CONT);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
sem_post(&pthread_pause_sem);
}
int pthread_pause(pthread_t thread) {
sem_wait(&pthread_pause_sem);
//If signal queue is full, we keep retrying
while(pthread_kill(thread, PTHREAD_XSIG_STOP) == EAGAIN) usleep(1000);
pthread_pause_yield();
return 0;
}
int pthread_unpause(pthread_t thread) {
sem_wait(&pthread_pause_sem);
//If signal queue is full, we keep retrying
while(pthread_kill(thread, PTHREAD_XSIG_CONT) == EAGAIN) usleep(1000);
pthread_pause_yield();
return 0;
}
void *thread_test() {
//Whole process dies if you kill thread immediately before it is pausable
//pthread_pause_enable();
while(1) {
//Printf() is not async signal safe (because it holds internal mutex),
//you should call it only with pause disabled!
//Will throw helgrind warnings anyway, not sure why...
//See: man 7 signal-safety
pthread_pause_disable();
printf("Running!\n");
pthread_pause_enable();
//Pausing main thread should not cause deadlock
//We pause main thread here just to test it is OK
pthread_pause(main_thread);
//pthread_nsleep(0, 1000*1000);
pthread_unpause(main_thread);
//Wait for a while
//pthread_nsleep(0, 1000*1000*100);
pthread_unpause(main_thread);
}
}
int main() {
pthread_t t;
main_thread = pthread_self();
pthread_pause_enable(); //Will get inherited by all threads from now on
//you need to call pthread_pause_enable (or disable) before creating threads,
//otherwise first (un)pause signal will kill whole process
pthread_create(&t, NULL, thread_test, NULL);
while(1) {
pthread_pause(t);
printf("PAUSED\n");
pthread_sleep(3);
printf("UNPAUSED\n");
pthread_unpause(t);
pthread_sleep(1);
/*
pthread_pause_disable();
printf("RUNNING!\n");
pthread_pause_enable();
*/
pthread_pause(t);
pthread_unpause(t);
}
pthread_join(t, NULL);
printf("DIEDED!\n");
}
I am also working on library called "pthread_extra", which will have stuff like this and much more. Will publish soon.
UPDATE2: This is still causing deadlocks when calling pause/unpause rapidly (removed sleep() calls). Printf() implementation in glibc has mutex, so if you suspend thread which is in middle of printf() and then want to printf() from your thread which plans to unpause that thread later, it will never happen, because printf() is locked. Unfortunately i've removed the printf() and only run empty while loop in the thread, but i still get deadlocks under high pause/unpause rates. and i don't know why. Maybe (even realtime) Linux signals are not 100% safe. There is realtime signal queue, maybe it just overflows or something...
UPDATE3: i think i've managed to fix the deadlock, but had to completely rewrite most of the code. Now i have one (sig_atomic_t) variable per each thread which holds state whether that thread should be running or not. Works kinda like condition variable. pthread_(un)pause() transparently remembers this for each thread. I don't have two signals. now i only have one signal. handler of that signal looks at that variable and only blocks on sigsuspend() when that variable says the thread should NOT run. otherwise it returns from signal handler. in order to suspend/resume the thread i now set the sig_atomic_t variable to desired state and call that signal (which is common for both suspend and resume). It is important to use realtime signals to be sure handler will actualy run after you've modified the state variable. Code is bit complex because of the thread status database. I will share the code in separate solution as soon as i manage to simplify it enough. But i want to preserve the two signal version in here, because it kinda works, i like the simplicity and maybe people will give us more insight on how to optimize it.
UPDATE4: I've fixed the deadlock in original code (no need for helper variable holding the status) by using single handler for two signals and optimizing signal queue a bit. There is still some problem with printf() shown by helgrind, but it is not caused by my signals, it happens even when i do not call pause/unpause at all. Overall this was only tested on LINUX, not sure how portable the code is, because there seem to be some undocumented behaviour of signal handlers which was originaly causing the deadlock.
Please note that pause/unpause cannot be nested. if you pause 3 times, and unpause 1 time, the thread WILL RUN. If you need such behaviour, you should create some kind of wrapper which will count the nesting levels and signal the thread accordingly.
UPDATE5: I've improved robustness of the code by following changes: I ensure proper serialization of pause/unpause calls by use of semaphores. This hopefuly fixes last remaining deadlocks. Now you can be sure that when pause call returns, the target thread is actualy already paused. This also solves issues with signal queue overflowing. Also i've added SA_RESTART flag, which prevents internal signals from causing interuption of IO waits. Sleeps/delays still have to be restarted manualy, but i provide convenient wrapper called pthread_nanosleep() which does just that.
UPDATE6: i realized that simply restarting nanosleep() is not enough, because that way timeout does not run when thread is paused. Therefore i've modified pthread_nanosleep() to convert timeout interval to absolute time point in the future and sleep until that. Also i've hidden semaphore initialization, so user does not need to do that.
Here is example of thread function within a class with pause/resume functionality...
class SomeClass
{
public:
// ... construction/destruction
void Resume();
void Pause();
void Stop();
private:
static void* ThreadFunc(void* pParam);
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t cond_var;
int command;
};
SomeClass::SomeClass()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond_var, NULL);
// create thread in suspended state..
command = 0;
pthread_create(&thread, NULL, ThreadFunc, this);
}
SomeClass::~SomeClass()
{
// we should stop the thread and exit ThreadFunc before calling of blocking pthread_join function
// also it prevents the mutex staying locked..
Stop();
pthread_join(thread, NULL);
pthread_cond_destroy(&cond_var);
pthread_mutex_destroy(&mutex);
}
void* SomeClass::ThreadFunc(void* pParam)
{
SomeClass* pThis = (SomeClass*)pParam;
timespec time_ns = {0, 50*1000*1000}; // 50 milliseconds
while(1)
{
pthread_mutex_lock(&pThis->mutex);
if (pThis->command == 2) // command to stop thread..
{
// be sure to unlock mutex before exit..
pthread_mutex_unlock(&pThis->mutex);
return NULL;
}
else if (pThis->command == 0) // command to pause thread..
{
pthread_cond_wait(&pThis->cond_var, &pThis->mutex);
// dont forget to unlock the mutex..
pthread_mutex_unlock(&pThis->mutex);
continue;
}
if (pThis->command == 1) // command to run..
{
// normal runing process..
fprintf(stderr, "*");
}
pthread_mutex_unlock(&pThis->mutex);
// it's important to give main thread few time after unlock 'this'
pthread_yield();
// ... or...
//nanosleep(&time_ns, NULL);
}
pthread_exit(NULL);
}
void SomeClass::Stop()
{
pthread_mutex_lock(&mutex);
command = 2;
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&mutex);
}
void SomeClass::Pause()
{
pthread_mutex_lock(&mutex);
command = 0;
// in pause command we dont need to signal cond_var because we not in wait state now..
pthread_mutex_unlock(&mutex);
}
void SomeClass::Resume()
{
pthread_mutex_lock(&mutex);
command = 1;
pthread_cond_signal(&cond_var);
pthread_mutex_unlock(&mutex);
}

PThread Question

I am trying to make a small thread example. I want to have a variable and each thread try to increment it and then stop once it gets to a certain point. Whenever the variable is locked, I want some sort of message to be printed out like "thread x trying to lock, but cannot" so that I KNOW it's working correctly. This is my first day coding threads so feel free to point out anything unnecessary in the code here -
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define NUM_THREADS 2
pthread_t threads[NUM_THREADS];
pthread_mutex_t mutexsum;
int NUMBER = 0;
void* increaseByHundred(void* threadid) {
if(pthread_mutex_lock(&mutexsum))
cout<<"\nTHREAD "<<(int)threadid<<" TRYING TO LOCK BUT CANNOT";
else {
for(int i=0;i<100;i++) {
NUMBER++;
cout<<"\nNUMBER: "<<NUMBER;
}
pthread_mutex_unlock(&mutexsum);
pthread_exit((void*)0);
}
}
int main(int argc, char** argv) {
int rc;
int rc1;
void* status;
pthread_attr_t attr;
pthread_mutex_init(&mutexsum, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
rc = pthread_create(&threads[0], &attr, increaseByHundred, (void*)0);
rc1 = pthread_create(&threads[1], &attr, increaseByHundred, (void*)1);
pthread_attr_destroy(&attr);
while(NUMBER < 400)
pthread_join(threads[0], &status);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
I was following a tutorial found here https://computing.llnl.gov/tutorials...reatingThreads
and tried to adapt their mutex example to this idea. The code increments it up to 199 and then stops. I'm guessing because the threads are only doing their routine once. Is there a way make them just do their routine other than when you create them so I could say
while something
do your routine
?
I have the pthread_join there just because it was similar to what that tutorial had on theirs. I don't really even get it that clearly though. I'm pretty sure that line is the problem...I just don't know how to fix it. Any help is appreciated.
Whenever the variable is locked, I want some sort of message to be printed out like "thread x trying to lock, but cannot" so that I KNOW it's working correctly.
Why do you want that? You are just learning about threads. Learn the basics first. Don't go diving off the deep end into pthread_mutex_trylock or mutexes configured for error checking. You need to learn to walk before you can learn how to run.
The basics involves a mutex initialized use with default settings and using pthread_mutex_lock to grab the lock. With the default settings, pthread_mutex_lock will only return non-zero if there are big, big problems. There are only two problems that can occur here: Deadlock, and a bad mutex pointer. There is no recovery from either; the only real solution is to fix the code. About the only thing you can do here is to throw an exception that you don't catch, call exit() or abort(), etc.
That some other thread has locked the mutex is not a big problem. It is not a problem at all. pthread_mutex_lock will block (e.g., go to sleep) until the lock becomes available. A zero return from pthread_mutex_lock means that the calling thread now has the lock. Just make sure you release the lock when you are done working with the protected memory.
Edit
Here's a suggestion that will let you see that the threading mechanism is working as advertised.
Upon entry to increaseByHundred print a time-stamped message indicating entry to the function. You probably want to use C printf here rather than C++ I/O. printf() and related functions are thread-safe. C++ 2003 I/O is not.
After a successful return from pthread_mutex_lock print another time-stamped message indicating that a successful lock.
sleep() for a few seconds and then print yet another time-stamped message prior to calling pthread_mutex_unlock().
Do the same before calling pthread_exit().
One last comment: You are checking for an error return from pthread_mutex_lock. For completeness, and because every good programmer is paranoid as all get out, you should also check the return status from pthread_mutex_unlock.
What about pthread_exit? It doesn't have a return status. You could print some message after calling pthread_exit, but you will only reach that statement if you are using a non-compliant version of the threads library. The function pthread_exit() cannot return to the calling function. Period. Worrying about what happens when pthreads_exit() returns is a tinfoil hat exercise. While good programmers should be paranoid beyond all get out, they should not be paranoid schizophrenic.
pthread_mutex_lock will normally just block until it acquire the lock, and that's why the line cout<<"\nTHREAD "<<(int)threadid<<" TRYING TO LOCK BUT CANNOT"; is not ran.
You also have problems in
while(NUMBER < 400)
pthread_join(threads[0], &status);
because you just have 2 threads and number will never reach 400. You also want to join thread[0] on first iteration, then thread[1]...
pthread_mutex_trylock():
if (pthread_mutex_trylock(&mutex) == EBUSY) {
cout << "OMG NO WAY ITS LOCKED" << endl;
}
It is also worth noting that if the mutex is not locked, it will be able to acquire the lock and then it will behave like a regular pthread_mutex_lock().