Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protecting main thread from errors in worker thread

When using posix threads, is there some way to "protect" the main thread from errors (such as dereferenced null pointers, division by zero, etc) caused by worker threads. By "worker thread" I mean a posix thread created by pthread_create().

Unfortunately, we cannot use exceptions - so no "catch", etc.

Here is my test program (C++):

void* workerThreadFunc(void* threadId) {
  int* a = NULL;
  *a = 5; //Error (segmentation fault)
  pthread_exit(NULL);
}

int main() {
  cout << "Main thread start" << endl;

  pthread_t workerThread;
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
  pthread_create(&workerThread, &attr, workerThreadFunc, (void*)0);
  pthread_join(workerThread, NULL);

  cout << "Main thread end" << endl;
}

In the example above, the error caused by workerThread will terminate the whole program. But I would like the main thread to continue running despite this error. Is this possible to achieve?

like image 711
Martin Avatar asked Sep 22 '14 09:09

Martin


2 Answers

Sounds to me like you should be using multiple processes, not threads. Independent processes are automatically protected from these sort of errors happening in other processes.

You can use pipes or shared memory (or other forms of IPC) to pass data between threads, which has the additional benefit of only sharing the memory you intend to share, so a bug in the worker "thread" cannot stomp on the stack of the main "thread", because it's a separate process with a separate address space.

Threads can be useful, but come with several disadvantages, sometimes running in separate processes is more appropriate.

like image 123
Jonathan Wakely Avatar answered Oct 11 '22 12:10

Jonathan Wakely


The only way I can think of doing this is registering a signal handler, which could instead of aborting the program, cancel the currently running thread, something like this:

void handler(int sig)
{
    pthread_exit(NULL);
}

signal(SIGSEGV, handler);

Note, however, this is unsafe as pthread_exit isn't listed as one of the safe system calls inside a signal handler. It might work and it might not, depending on the O/S you're running under, and on what signal you're handling.

like image 41
Tom Tanner Avatar answered Oct 11 '22 12:10

Tom Tanner