2010-07-30 Hui Zhu <teawater@gmail.com>
[deliverable/binutils-gdb.git] / gdb / mingw-hdep.c
CommitLineData
121ce6e5
DJ
1/* Host support routines for MinGW, for GDB, the GNU debugger.
2
4c38e0a4 3 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
121ce6e5
DJ
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
121ce6e5
DJ
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
121ce6e5
DJ
19
20#include "defs.h"
0ea3f30e 21#include "serial.h"
b803fb0f 22#include "event-loop.h"
121ce6e5 23
0ea3f30e
DJ
24#include "gdb_assert.h"
25#include "gdb_select.h"
121ce6e5 26#include "gdb_string.h"
b803fb0f 27#include "readline/readline.h"
121ce6e5
DJ
28
29#include <windows.h>
30
b803fb0f
DJ
31/* This event is signalled whenever an asynchronous SIGINT handler
32 needs to perform an action in the main thread. */
33static HANDLE sigint_event;
34
35/* When SIGINT_EVENT is signalled, gdb_select will call this
36 function. */
37struct async_signal_handler *sigint_handler;
38
121ce6e5
DJ
39/* The strerror() function can return NULL for errno values that are
40 out of range. Provide a "safe" version that always returns a
41 printable string.
42
43 The Windows runtime implementation of strerror never returns NULL,
44 but does return a useless string for anything above sys_nerr;
45 unfortunately this includes all socket-related error codes.
46 This replacement tries to find a system-provided error message. */
47
48char *
49safe_strerror (int errnum)
50{
51 static char *buffer;
52 int len;
53
54 if (errnum >= 0 && errnum < sys_nerr)
55 return strerror (errnum);
56
57 if (buffer)
58 {
59 LocalFree (buffer);
60 buffer = NULL;
61 }
62
63 if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
64 | FORMAT_MESSAGE_FROM_SYSTEM,
65 NULL, errnum,
66 MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
67 (LPTSTR) &buffer, 0, NULL) == 0)
68 {
69 static char buf[32];
70 xsnprintf (buf, sizeof buf, "(undocumented errno %d)", errnum);
71 return buf;
72 }
73
74 /* Windows error messages end with a period and a CR-LF; strip that
75 out. */
76 len = strlen (buffer);
77 if (len > 3 && strcmp (buffer + len - 3, ".\r\n") == 0)
78 buffer[len - 3] = '\0';
79
80 return buffer;
81}
0ea3f30e
DJ
82
83/* Wrapper for select. On Windows systems, where the select interface
84 only works for sockets, this uses the GDB serial abstraction to
85 handle sockets, consoles, pipes, and serial ports.
86
87 The arguments to this function are the same as the traditional
88 arguments to select on POSIX platforms. */
89
90int
91gdb_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
92 struct timeval *timeout)
93{
94 static HANDLE never_handle;
95 HANDLE handles[MAXIMUM_WAIT_OBJECTS];
96 HANDLE h;
97 DWORD event;
98 DWORD num_handles;
4577549b
DJ
99 /* SCBS contains serial control objects corresponding to file
100 descriptors in READFDS and WRITEFDS. */
101 struct serial *scbs[MAXIMUM_WAIT_OBJECTS];
102 /* The number of valid entries in SCBS. */
103 size_t num_scbs;
0ea3f30e
DJ
104 int fd;
105 int num_ready;
4577549b 106 size_t indx;
0ea3f30e
DJ
107
108 num_ready = 0;
109 num_handles = 0;
4577549b 110 num_scbs = 0;
0ea3f30e
DJ
111 for (fd = 0; fd < n; ++fd)
112 {
113 HANDLE read = NULL, except = NULL;
114 struct serial *scb;
115
116 /* There is no support yet for WRITEFDS. At present, this isn't
117 used by GDB -- but we do not want to silently ignore WRITEFDS
118 if something starts using it. */
119 gdb_assert (!writefds || !FD_ISSET (fd, writefds));
120
98739726
DJ
121 if ((!readfds || !FD_ISSET (fd, readfds))
122 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
0ea3f30e 123 continue;
0ea3f30e
DJ
124
125 scb = serial_for_fd (fd);
126 if (scb)
4577549b
DJ
127 {
128 serial_wait_handle (scb, &read, &except);
129 scbs[num_scbs++] = scb;
130 }
0ea3f30e
DJ
131
132 if (read == NULL)
4577549b 133 read = (HANDLE) _get_osfhandle (fd);
0ea3f30e
DJ
134 if (except == NULL)
135 {
136 if (!never_handle)
137 never_handle = CreateEvent (0, FALSE, FALSE, 0);
138
139 except = never_handle;
140 }
141
98739726 142 if (readfds && FD_ISSET (fd, readfds))
0ea3f30e
DJ
143 {
144 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
145 handles[num_handles++] = read;
146 }
147
98739726 148 if (exceptfds && FD_ISSET (fd, exceptfds))
0ea3f30e
DJ
149 {
150 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
151 handles[num_handles++] = except;
152 }
153 }
0ea3f30e 154
b803fb0f
DJ
155 gdb_assert (num_handles < MAXIMUM_WAIT_OBJECTS);
156 handles[num_handles++] = sigint_event;
0ea3f30e
DJ
157
158 event = WaitForMultipleObjects (num_handles,
159 handles,
160 FALSE,
161 timeout
162 ? (timeout->tv_sec * 1000
163 + timeout->tv_usec / 1000)
164 : INFINITE);
165 /* EVENT can only be a value in the WAIT_ABANDONED_0 range if the
166 HANDLES included an abandoned mutex. Since GDB doesn't use
167 mutexes, that should never occur. */
168 gdb_assert (!(WAIT_ABANDONED_0 <= event
169 && event < WAIT_ABANDONED_0 + num_handles));
4577549b
DJ
170 /* We no longer need the helper threads to check for activity. */
171 for (indx = 0; indx < num_scbs; ++indx)
172 serial_done_wait_handle (scbs[indx]);
0ea3f30e
DJ
173 if (event == WAIT_FAILED)
174 return -1;
175 if (event == WAIT_TIMEOUT)
176 return 0;
177 /* Run through the READFDS, clearing bits corresponding to descriptors
178 for which input is unavailable. */
179 h = handles[event - WAIT_OBJECT_0];
180 for (fd = 0, indx = 0; fd < n; ++fd)
181 {
182 HANDLE fd_h;
c3e2b812 183
98739726
DJ
184 if ((!readfds || !FD_ISSET (fd, readfds))
185 && (!exceptfds || !FD_ISSET (fd, exceptfds)))
c3e2b812 186 continue;
0ea3f30e 187
98739726 188 if (readfds && FD_ISSET (fd, readfds))
0ea3f30e
DJ
189 {
190 fd_h = handles[indx++];
191 /* This handle might be ready, even though it wasn't the handle
192 returned by WaitForMultipleObjects. */
193 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
194 FD_CLR (fd, readfds);
195 else
196 num_ready++;
197 }
198
98739726 199 if (exceptfds && FD_ISSET (fd, exceptfds))
0ea3f30e
DJ
200 {
201 fd_h = handles[indx++];
202 /* This handle might be ready, even though it wasn't the handle
203 returned by WaitForMultipleObjects. */
204 if (fd_h != h && WaitForSingleObject (fd_h, 0) != WAIT_OBJECT_0)
205 FD_CLR (fd, exceptfds);
206 else
207 num_ready++;
208 }
209 }
210
b803fb0f
DJ
211 /* With multi-threaded SIGINT handling, there is a race between the
212 readline signal handler and GDB. It may still be in
213 rl_prep_terminal in another thread. Do not return until it is
214 done; we can check the state here because we never longjmp from
215 signal handlers on Windows. */
216 while (RL_ISSTATE (RL_STATE_SIGHANDLER))
217 Sleep (1);
218
219 if (h == sigint_event
220 || WaitForSingleObject (sigint_event, 0) == WAIT_OBJECT_0)
221 {
222 if (sigint_handler != NULL)
223 call_async_signal_handler (sigint_handler);
224
225 if (num_ready == 0)
226 {
227 errno = EINTR;
228 return -1;
229 }
230 }
231
0ea3f30e
DJ
232 return num_ready;
233}
b803fb0f
DJ
234
235/* Wrapper for the body of signal handlers. On Windows systems, a
236 SIGINT handler runs in its own thread. We can't longjmp from
237 there, and we shouldn't even prompt the user. Delay HANDLER
238 until the main thread is next in gdb_select. */
239
240void
241gdb_call_async_signal_handler (struct async_signal_handler *handler,
242 int immediate_p)
243{
244 if (immediate_p)
245 sigint_handler = handler;
246 else
247 {
248 mark_async_signal_handler (handler);
249 sigint_handler = NULL;
250 }
251 SetEvent (sigint_event);
252}
253
254void
255_initialize_mingw_hdep (void)
256{
257 sigint_event = CreateEvent (0, FALSE, FALSE, 0);
258}
This page took 0.371233 seconds and 4 git commands to generate.