mingw-hdep.c revision 1.5
1/* Host support routines for MinGW, for GDB, the GNU debugger. 2 3 Copyright (C) 2006-2015 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#include "defs.h" 21#include "main.h" 22#include "serial.h" 23#include "event-loop.h" 24 25#include "gdb_select.h" 26#include "readline/readline.h" 27 28#include <windows.h> 29 30/* This event is signalled whenever an asynchronous SIGINT handler 31 needs to perform an action in the main thread. */ 32static HANDLE sigint_event; 33 34/* When SIGINT_EVENT is signalled, gdb_select will call this 35 function. */ 36struct async_signal_handler *sigint_handler; 37 38/* Return an absolute file name of the running GDB, if possible, or 39 ARGV0 if not. The return value is in malloc'ed storage. */ 40 41char * 42windows_get_absolute_argv0 (const char *argv0) 43{ 44 char full_name[PATH_MAX]; 45 46 if (GetModuleFileName (NULL, full_name, PATH_MAX)) 47 return xstrdup (full_name); 48 return xstrdup (argv0); 49} 50 51/* Wrapper for select. On Windows systems, where the select interface 52 only works for sockets, this uses the GDB serial abstraction to 53 handle sockets, consoles, pipes, and serial ports. 54 55 The arguments to this function are the same as the traditional 56 arguments to select on POSIX platforms. */ 57 58int 59gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 60 struct timeval *timeout) 61{ 62 static HANDLE never_handle; 63 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 64 HANDLE h; 65 DWORD event; 66 DWORD num_handles; 67 /* SCBS contains serial control objects corresponding to file 68 descriptors in READFDS and WRITEFDS. */ 69 struct serial *scbs[MAXIMUM_WAIT_OBJECTS]; 70 /* The number of valid entries in SCBS. */ 71 size_t num_scbs; 72 int fd; 73 int num_ready; 74 size_t indx; 75 76 num_ready = 0; 77 num_handles = 0; 78 num_scbs = 0; 79 for (fd = 0; fd < n; ++fd) 80 { 81 HANDLE read = NULL, except = NULL; 82 struct serial *scb; 83 84 /* There is no support yet for WRITEFDS. At present, this isn't 85 used by GDB -- but we do not want to silently ignore WRITEFDS 86 if something starts using it. */ 87 gdb_assert (!writefds || !FD_ISSET (fd, writefds)); 88 89 if ((!readfds || !FD_ISSET (fd, readfds)) 90 && (!exceptfds || !FD_ISSET (fd, exceptfds))) 91 continue; 92 93 scb = serial_for_fd (fd); 94 if (scb) 95 { 96 serial_wait_handle (scb, &read, &except); 97 scbs[num_scbs++] = scb; 98 } 99 100 if (read == NULL) 101 read = (HANDLE) _get_osfhandle (fd); 102 if (except == NULL) 103 { 104 if (!never_handle) 105 never_handle = CreateEvent (0, FALSE, FALSE, 0); 106 107 except = never_handle; 108 } 109 110 if (readfds && FD_ISSET (fd, readfds)) 111 { 112 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS); 113 handles[num_handles++] = read; 114 } 115 116 if (exceptfds && FD_ISSET (fd, exceptfds)) 117 { 118 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS); 119 handles[num_handles++] = except; 120 } 121 } 122 123 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS); 124 handles[num_handles++] = sigint_event; 125 126 event = WaitForMultipleObjects (num_handles, 127 handles, 128 FALSE, 129 timeout 130 ? (timeout->tv_sec * 1000 131 + timeout->tv_usec / 1000) 132 : INFINITE); 133 /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the 134 HANDLES included an abandoned mutex. Since GDB doesn't use 135 mutexes, that should never occur. */ 136 gdb_assert (!(WAIT_ABANDONED_0 <= event 137 && event < WAIT_ABANDONED_0 + num_handles)); 138 /* We no longer need the helper threads to check for activity. */ 139 for (indx = 0; indx < num_scbs; ++indx) 140 serial_done_wait_handle (scbs[indx]); 141 if (event == WAIT_FAILED) 142 return -1; 143 if (event == WAIT_TIMEOUT) 144 return 0; 145 /* Run through the READFDS, clearing bits corresponding to descriptors 146 for which input is unavailable. */ 147 h = handles[event - WAIT_OBJECT_0]; 148 for (fd = 0, indx = 0; fd < n; ++fd) 149 { 150 HANDLE fd_h; 151 152 if ((!readfds || !FD_ISSET (fd, readfds)) 153 && (!exceptfds || !FD_ISSET (fd, exceptfds))) 154 continue; 155 156 if (readfds && FD_ISSET (fd, readfds)) 157 { 158 fd_h = handles[indx++]; 159 /* This handle might be ready, even though it wasn't the handle 160 returned by WaitForMultipleObjects. */ 161 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0) 162 FD_CLR (fd, readfds); 163 else 164 num_ready++; 165 } 166 167 if (exceptfds && FD_ISSET (fd, exceptfds)) 168 { 169 fd_h = handles[indx++]; 170 /* This handle might be ready, even though it wasn't the handle 171 returned by WaitForMultipleObjects. */ 172 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0) 173 FD_CLR (fd, exceptfds); 174 else 175 num_ready++; 176 } 177 } 178 179 /* With multi-threaded SIGINT handling, there is a race between the 180 readline signal handler and GDB. It may still be in 181 rl_prep_terminal in another thread. Do not return until it is 182 done; we can check the state here because we never longjmp from 183 signal handlers on Windows. */ 184 while (RL_ISSTATE (RL_STATE_SIGHANDLER)) 185 Sleep (1); 186 187 if (h == sigint_event 188 || WaitForSingleObject (sigint_event, 0) == WAIT_OBJECT_0) 189 { 190 if (sigint_handler != NULL) 191 call_async_signal_handler (sigint_handler); 192 193 if (num_ready == 0) 194 { 195 errno = EINTR; 196 return -1; 197 } 198 } 199 200 return num_ready; 201} 202 203/* Wrapper for the body of signal handlers. On Windows systems, a 204 SIGINT handler runs in its own thread. We can't longjmp from 205 there, and we shouldn't even prompt the user. Delay HANDLER 206 until the main thread is next in gdb_select. */ 207 208void 209gdb_call_async_signal_handler (struct async_signal_handler *handler, 210 int immediate_p) 211{ 212 if (immediate_p) 213 sigint_handler = handler; 214 else 215 { 216 mark_async_signal_handler (handler); 217 sigint_handler = NULL; 218 } 219 SetEvent (sigint_event); 220} 221 222/* -Wmissing-prototypes */ 223extern initialize_file_ftype _initialize_mingw_hdep; 224 225void 226_initialize_mingw_hdep (void) 227{ 228 sigint_event = CreateEvent (0, FALSE, FALSE, 0); 229} 230