gdb/nat/linux-waitpid.c - gdb

Functions defined

Source code

  1. /* Wrapper implementation for waitpid for GNU/Linux (LWP layer).

  2.    Copyright (C) 2001-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "common-defs.h"

  15. #ifdef GDBSERVER
  16. /* FIXME: server.h is required for the definition of debug_threads
  17.    which is used in the gdbserver-specific debug printing in
  18.    linux_debug.  This code should be made available to GDB also,
  19.    but the lack of a suitable flag to enable it prevents this.  */
  20. #include "server.h"
  21. #endif

  22. #include "linux-nat.h"
  23. #include "linux-waitpid.h"
  24. #include "gdb_wait.h"

  25. /* Print debugging output based on the format string FORMAT and
  26.    its parameters.  */

  27. static inline void
  28. linux_debug (const char *format, ...)
  29. {
  30. #ifdef GDBSERVER
  31.   if (debug_threads)
  32.     {
  33.       va_list args;
  34.       va_start (args, format);
  35.       vfprintf (stderr, format, args);
  36.       va_end (args);
  37.     }
  38. #endif
  39. }

  40. /* Convert wait status STATUS to a string.  Used for printing debug
  41.    messages only.  */

  42. char *
  43. status_to_str (int status)
  44. {
  45.   static char buf[64];

  46.   if (WIFSTOPPED (status))
  47.     {
  48.       if (WSTOPSIG (status) == SYSCALL_SIGTRAP)
  49.         snprintf (buf, sizeof (buf), "%s (stopped at syscall)",
  50.                   strsignal (SIGTRAP));
  51.       else
  52.         snprintf (buf, sizeof (buf), "%s (stopped)",
  53.                   strsignal (WSTOPSIG (status)));
  54.     }
  55.   else if (WIFSIGNALED (status))
  56.     snprintf (buf, sizeof (buf), "%s (terminated)",
  57.               strsignal (WTERMSIG (status)));
  58.   else
  59.     snprintf (buf, sizeof (buf), "%d (exited)", WEXITSTATUS (status));

  60.   return buf;
  61. }

  62. /* Wrapper function for waitpid which handles EINTR, and emulates
  63.    __WALL for systems where that is not available.  */

  64. int
  65. my_waitpid (int pid, int *status, int flags)
  66. {
  67.   int ret, out_errno;

  68.   linux_debug ("my_waitpid (%d, 0x%x)\n", pid, flags);

  69.   if (flags & __WALL)
  70.     {
  71.       sigset_t block_mask, org_mask, wake_mask;
  72.       int wnohang;

  73.       wnohang = (flags & WNOHANG) != 0;
  74.       flags &= ~(__WALL | __WCLONE);

  75.       if (!wnohang)
  76.         {
  77.           flags |= WNOHANG;

  78.           /* Block all signals while here.  This avoids knowing about
  79.              LinuxThread's signals.  */
  80.           sigfillset (&block_mask);
  81.           sigprocmask (SIG_BLOCK, &block_mask, &org_mask);

  82.           /* ... except during the sigsuspend below.  */
  83.           sigemptyset (&wake_mask);
  84.         }

  85.       while (1)
  86.         {
  87.           /* Since all signals are blocked, there's no need to check
  88.              for EINTR here.  */
  89.           ret = waitpid (pid, status, flags);
  90.           out_errno = errno;

  91.           if (ret == -1 && out_errno != ECHILD)
  92.             break;
  93.           else if (ret > 0)
  94.             break;

  95.           if (flags & __WCLONE)
  96.             {
  97.               /* We've tried both flavors now.  If WNOHANG is set,
  98.                  there's nothing else to do, just bail out.  */
  99.               if (wnohang)
  100.                 break;

  101.               linux_debug ("blocking\n");

  102.               /* Block waiting for signals.  */
  103.               sigsuspend (&wake_mask);
  104.             }
  105.           flags ^= __WCLONE;
  106.         }

  107.       if (!wnohang)
  108.         sigprocmask (SIG_SETMASK, &org_mask, NULL);
  109.     }
  110.   else
  111.     {
  112.       do
  113.         ret = waitpid (pid, status, flags);
  114.       while (ret == -1 && errno == EINTR);
  115.       out_errno = errno;
  116.     }

  117.   linux_debug ("my_waitpid (%d, 0x%x): status(%x), %d\n",
  118.                pid, flags, status ? *status : -1, ret);

  119.   errno = out_errno;
  120.   return ret;
  121. }