2

I want to know if there is an easy way to catch the id of the thread who crash without using intermediates signal_handlers

I have the following code

void signal_handler(int signal)
{
  std::cout << "Caught the signal:" << signal << std::endl;
}

void    handler_t1(int signal)
{
  std::signal(SIGSEGV, signal_handler);
  std::cout << "Thread 1 have received the signal: " << signal << std::endl;
  std::raise(SIGSEGV);
}

void    f1()
{
  std::signal(SIGSEGV, handler_t1);
  std::cout << "Begin thread 1" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(1));
  std::raise(SIGSEGV);
  std::cout << "end thread1" << std::endl;
}

void    f2()
{
  std::cout << "Begin thread 2" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(3));
  std::cout << "end thread2" << std::endl;
}

int     main()
{
  std::thread t1(f1);
  std::thread t2(f2);

  t1.join();
  t2.join();
}

So I get the

Begin thread 1Begin thread 2
Thread 1 have received the signal: 11
Caught the signal:11
end thread1
end thread2

But if I have 5 threads, can I avoid to create 5 handler ?

edit my includes are

#include <thread>
#include <chrono>
#include <iostream>
#include <csignal>

edit I think I was looking something like I found https://stackoverflow.com/a/16259324/2380470 but since this thing doesn't exist yet, I must find something else

Community
  • 1
  • 1
Alexis
  • 2,149
  • 2
  • 25
  • 39
  • In general a signal won't be thrown from one of your own threads, so I'm not sure this makes sense. What if it came from `kill -s SIGSEGV `? – BoBTFish Jul 24 '13 at 14:34
  • @Alexis would you mind posting the appropriate includes with your code? I might be interested in some parts of your question. – hetepeperfan Jul 24 '13 at 14:41
  • @hetepeperfan the includes that I found on the std website (edited my question) – Alexis Jul 24 '13 at 16:13

2 Answers2

5

The answer to your question is "No". You can control the thread in which a software interrupt executes asynchronously (by blocking the signal in particular threads); and on a POSIX platform you can block the asynchronous execution of signals in all threads, and instead respond to signals in a dedicated thread using sigwait(). But where the interrupt occurs by virtue of a call to kill(), or is a system generated interrupt such as SIGSEGV, there is no standard way in POSIX of determining in the signal handler what thread generated the signal.

Note that threads do not "throw" a signal. Note also that none of this is relevant to the C++ standard.

Edit I notice that one of your commenters may assume that a signal handler executes in the thread in which the signal was generated. Except in the case of a call to raise(), that is not the case. A signal arising from kill() or which is system generated can execute asynchronously in whatever thread has not blocked that signal. If more than one thread has the signal unblocked, it is undefined which thread is interrupted (that is the choice of the system and its scheduler). Note also that where an interrupt is user generated, in POSIX sigqueue() can be called instead of kill(), and sigqueue can pass in a user data value which can identify, say, the identity of the caller. However that is obviously irrelevant to SIGSEGV. In POSIX, using pthread_kill() you can also cause a signal to interrupt a particular thread in the process in which the call is made (but that doesn't identify the caller, nor is it relevant to SIGSEGV). raise() in a multi-threaded program has effect as a call to pthread_kill() (it will execute in the thread calling raise(): but raise() is useless for information passing purposes).

Chris Vine
  • 677
  • 3
  • 7
1

gettid() will give you the id of the thread that calls it. This will give you what you want!

http://linux.die.net/man/2/gettid

If you store your threads in a thread buffer of some sort too, you could always just label them yourself based on where they're located in the array (e.g. thread 0 -> n for threads[n])

KrisSodroski
  • 2,796
  • 3
  • 24
  • 39