5

I want to profile my daemon program, that pauses the main thread:

sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGTERM);
sigaddset(&signal_mask, SIGINT);

int sig;
sigwait(&signal_mask, &sig);

All other threads simply block all signals. As far as I know the profiler uses SIGPROF signal for its operations. If I start profiling with such a code, the output .prof file is empty:

env CPUPROFILE=daemon.prof ./daemon

How should I properly handle signals in main thread and other threads to enable profiling? Or may be an issue is somewhere else?

abyss.7
  • 13,882
  • 11
  • 56
  • 100

2 Answers2

1

All other threads simply block all signals.

You simply need to unblock SIGPROF in all threads (or in those that you want to profile). We were just solving exactly the same problem in a multi-threaded daemon.

0

I need to see more of your code, but your statement that "All other threads simply block all signals" raises...signals.

You have to remember that most system calls were created before the concept of threads existed. Signal handling is one of them. Thus, when you block a signal on ANY thread, it's likely blocked for ALL threads.

In fact, check out the signal(2) manpage:

The effects of signal() in a multithreaded process are unspecified.

Yes, this is sad, but it is the price you must pay for using a low-overhead statistical sampling profiler. And working around it is very easy: just remove SIGPROF (or SIGALRM if you are using the REAL mode) from your signal mask set and you should be fine.

And in general, unless you absolutely have to, you should not be doing process-level signal masking in anything other than the main thread...where "main" doesn't necessarily mean the thread that MAIN() is running in, but rather, the thread you consider the "boss" of all the others, for reasons you have made all too clear already. :)

You can also try using the pthread library's sigmask wrapper pthread_sigmask, but it is unclear to me how well it works in situations such as a child thread REMOVING an entry from a sigmask (pthreads inherit their parent's pthread sigmask).

Mark Gerolimatos
  • 2,424
  • 1
  • 23
  • 33
  • At least in Linux, there are two kinds of signals, process-wide (to be delivered to any thread) and per-pthread (one can send signal directly to specific thread). Still don't know, which kind of signal was used by `setitimer` (which sends SIGPROF/SIGALRM) ([my own question](http://stackoverflow.com/q/2586926/196561)). Update: the topic https://groups.google.com/forum/#!topic/linux.kernel/DF-VwEf2AqE says that `setitimer` used per-thread signals. – osgx Apr 14 '14 at 00:50