GDB (API)
|
00001 /* Wrapper implementation for waitpid for GNU/Linux (LWP layer). 00002 00003 Copyright (C) 2001-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #ifdef GDBSERVER 00021 #include "server.h" 00022 #else 00023 #include "defs.h" 00024 #include "signal.h" 00025 #endif 00026 00027 #include "nat/linux-nat.h" 00028 #include "nat/linux-waitpid.h" 00029 #include "gdb_wait.h" 00030 00031 /* Print debugging output based on the format string FORMAT and 00032 its parameters. */ 00033 00034 static inline void 00035 linux_debug (const char *format, ...) 00036 { 00037 #ifdef GDBSERVER 00038 if (debug_threads) 00039 { 00040 va_list args; 00041 va_start (args, format); 00042 vfprintf (stderr, format, args); 00043 fprintf (stderr, "\n"); 00044 va_end (args); 00045 } 00046 #else 00047 /* GDB-specific debugging output. */ 00048 #endif 00049 } 00050 00051 /* Wrapper function for waitpid which handles EINTR, and emulates 00052 __WALL for systems where that is not available. */ 00053 00054 int 00055 my_waitpid (int pid, int *status, int flags) 00056 { 00057 int ret, out_errno; 00058 00059 linux_debug ("my_waitpid (%d, 0x%x)\n", pid, flags); 00060 00061 if (flags & __WALL) 00062 { 00063 sigset_t block_mask, org_mask, wake_mask; 00064 int wnohang; 00065 00066 wnohang = (flags & WNOHANG) != 0; 00067 flags &= ~(__WALL | __WCLONE); 00068 flags |= WNOHANG; 00069 00070 /* Block all signals while here. This avoids knowing about 00071 LinuxThread's signals. */ 00072 sigfillset (&block_mask); 00073 sigprocmask (SIG_BLOCK, &block_mask, &org_mask); 00074 00075 /* ... except during the sigsuspend below. */ 00076 sigemptyset (&wake_mask); 00077 00078 while (1) 00079 { 00080 /* Since all signals are blocked, there's no need to check 00081 for EINTR here. */ 00082 ret = waitpid (pid, status, flags); 00083 out_errno = errno; 00084 00085 if (ret == -1 && out_errno != ECHILD) 00086 break; 00087 else if (ret > 0) 00088 break; 00089 00090 if (flags & __WCLONE) 00091 { 00092 /* We've tried both flavors now. If WNOHANG is set, 00093 there's nothing else to do, just bail out. */ 00094 if (wnohang) 00095 break; 00096 00097 linux_debug ("blocking\n"); 00098 00099 /* Block waiting for signals. */ 00100 sigsuspend (&wake_mask); 00101 } 00102 flags ^= __WCLONE; 00103 } 00104 00105 sigprocmask (SIG_SETMASK, &org_mask, NULL); 00106 } 00107 else 00108 { 00109 do 00110 ret = waitpid (pid, status, flags); 00111 while (ret == -1 && errno == EINTR); 00112 out_errno = errno; 00113 } 00114 00115 linux_debug ("my_waitpid (%d, 0x%x): status(%x), %d\n", 00116 pid, flags, status ? *status : -1, ret); 00117 00118 errno = out_errno; 00119 return ret; 00120 }