This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: determine whether code is running in a signal handler context


Hi friends,

Still remember this thread? It turn out that determining whether or not you
are currently in a signal handler is trivial with libunwind:

Assume that you have build libunwind properly:

------------------------------------
  #include <pthread.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <signal.h>
  #include <errno.h>
  #include <string.h>

  /* assume that you have build libunwind properly */
  #include "./libunwindout/include/libunwind.h"

  /* Simple error handling functions */
  #define handle_error_en(en, msg) \
          do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

  void show_backtrace(void) {
      unw_cursor_t cursor; unw_context_t uc;
      unw_word_t ip, sp;

      unw_getcontext(&uc);
      unw_init_local(&cursor, &uc);
      while(unw_step(&cursor) > 0) {
          unw_get_reg(&cursor, UNW_REG_IP, &ip);
          unw_get_reg(&cursor, UNW_REG_SP, &sp);

          /* Upon unwinding to a signal handler, you get a "1" */
          printf("Is in a signal handler [%d]\n",
                            unw_is_signal_frame(&cursor));

          printf("ip = %lx, sp = %lx \n", (long)ip, (long)sp);
      }
  }

  struct sigaction act;

  /* Upon receiving a SIGQUIT, this signal handler will be invoked */
  void sighandler(int signum, siginfo_t *info, void *ptr) {
      printf("Received signal: %d\n", signum);
      printf("signal originate from pid[%d]\n", info->si_pid);
      printf("Inside a signal handler...\n");
      show_backtrace();
      while(1)
          ;
      printf("[FATAL] quiting the signal handler\n");
  }

  int main(int argc, char *argv[]) {
  {
      printf("Pid of the current process: %d\n", getpid());

      memset(&act, 0, sizeof(act));

      act.sa_sigaction = sighandler;
      act.sa_flags = SA_SIGINFO;

      sigaction(SIGQUIT, &act, NULL);

      while(1)
         ;

      return 0;
  }
------------------ END -------------

So you should run this program, and then send it a SIGQUIT. Upon receiving a
SIGQUIT, the signal handler will be invoked and the show_backtrace() function
will be called, which will unwind the stack and eventually find the signal
handler frame, reporting 1.

More interesting, libunwind allows you to detect "remotely" with its
libunwind-ptrace module. By "remotely", it simply means that you can use
ptrace(2) to attach to a process and then you can use libunwind-ptrace to
detect the remote process is running in a signal handler.

For more info, please refer to libunwind's doc [1].

As of the mechanism which libunwind use, somebody refer to sigreturn(2) [2],
but I still investigate in that so more material will be pending.

Anyway, thank you for all your patience and discussion.

[1]: http://www.nongnu.org/libunwind/docs.html
[2]: https://stackoverflow.com/questions/47503630/detect-whether-tracee-is-in-a-signal-handler-when-using-ptrace/47503853

        Yubin

2017-10-18 22:18 GMT+08:00 Yubin Ruan <ablacktshirt@gmail.com>:
> Hi,
>
> I am writing to see if this is any util functions in libc that can
> help to determine it is currently running in a signal.
>
> I wrote some library and provide a function which will be used in many
> client code. However this function is not async-signal safe (it calls
> malloc(3)) so when it is called, I want to detect whether it is
> currently running in a signal handler. If it is, I can avoid calling
> those not-async-signal-safe functions which might cause deadlock.
>
> that is, I want a `in_signal_handler_context()' utility that can be
> used as this:
>
> int mylibfunc( void ) {
>     if( in_signal_handler_context() ) { return(-1) }
>     // rest of function goes here
>     return( 0 );
> }
>
>
> Yubin


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]