]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/ser-event.c
Fix latent bug in custom word point completion handling
[thirdparty/binutils-gdb.git] / gdb / ser-event.c
1 /* Serial interface for a selectable event.
2 Copyright (C) 2016-2019 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18
19 #include "defs.h"
20 #include "ser-event.h"
21 #include "serial.h"
22 #include "common/filestuff.h"
23
24 /* On POSIX hosts, a serial_event is basically an abstraction for the
25 classical self-pipe trick.
26
27 On Windows, a serial_event is a wrapper around a native Windows
28 event object. Because we want to interface with gdb_select, which
29 takes file descriptors, we need to wrap that Windows event object
30 in a file descriptor. As _open_osfhandle can not be used with
31 event objects, we instead create a dummy file wrap that in a file
32 descriptor with _open_osfhandle, and pass that as selectable
33 descriptor to callers. As Windows' gdb_select converts file
34 descriptors back to Windows handles by calling serial->wait_handle,
35 nothing ever actually waits on that file descriptor. */
36
37 struct serial_event_state
38 {
39 #ifdef USE_WIN32API
40 /* The Windows event object, created with CreateEvent. */
41 HANDLE event;
42 #else
43 /* The write side of the pipe. The read side is in
44 serial->fd. */
45 int write_fd;
46 #endif
47 };
48
49 /* Open a new serial event. */
50
51 static int
52 serial_event_open (struct serial *scb, const char *name)
53 {
54 struct serial_event_state *state;
55
56 state = XNEW (struct serial_event_state);
57 scb->state = state;
58
59 #ifndef USE_WIN32API
60 {
61 int fds[2];
62
63 if (gdb_pipe_cloexec (fds) == -1)
64 internal_error (__FILE__, __LINE__,
65 "creating serial event pipe failed.");
66
67 fcntl (fds[0], F_SETFL, O_NONBLOCK);
68 fcntl (fds[1], F_SETFL, O_NONBLOCK);
69
70 scb->fd = fds[0];
71 state->write_fd = fds[1];
72 }
73 #else
74 {
75 /* A dummy file object that can be wrapped in a file descriptor.
76 We don't need to store this handle because closing the file
77 descriptor automatically closes this. */
78 HANDLE dummy_file;
79
80 /* A manual-reset event. */
81 state->event = CreateEvent (0, TRUE, FALSE, 0);
82
83 /* The dummy file handle. Created just so we have something
84 wrappable in a file descriptor. */
85 dummy_file = CreateFile ("nul", 0, 0, NULL, OPEN_EXISTING, 0, NULL);
86 scb->fd = _open_osfhandle ((intptr_t) dummy_file, 0);
87 }
88 #endif
89
90 return 0;
91 }
92
93 static void
94 serial_event_close (struct serial *scb)
95 {
96 struct serial_event_state *state = (struct serial_event_state *) scb->state;
97
98 close (scb->fd);
99 #ifndef USE_WIN32API
100 close (state->write_fd);
101 #else
102 CloseHandle (state->event);
103 #endif
104
105 scb->fd = -1;
106
107 xfree (state);
108 scb->state = NULL;
109 }
110
111 #ifdef USE_WIN32API
112
113 /* Implementation of the wait_handle method. Returns the native
114 Windows event object handle. */
115
116 static void
117 serial_event_wait_handle (struct serial *scb, HANDLE *read, HANDLE *except)
118 {
119 struct serial_event_state *state = (struct serial_event_state *) scb->state;
120
121 *read = state->event;
122 }
123
124 #endif
125
126 /* The serial_ops for struct serial_event objects. Note we never
127 register this serial type with serial_add_interface, because this
128 is internal implementation detail never to be used by remote
129 targets for protocol transport. */
130
131 static const struct serial_ops serial_event_ops =
132 {
133 "event",
134 serial_event_open,
135 serial_event_close,
136 NULL, /* fdopen */
137 NULL, /* readchar */
138 NULL, /* write */
139 NULL, /* flush_output */
140 NULL, /* flush_input */
141 NULL, /* send_break */
142 NULL, /* go_raw */
143 NULL, /* get_tty_state */
144 NULL, /* copy_tty_state */
145 NULL, /* set_tty_state */
146 NULL, /* print_tty_state */
147 NULL, /* setbaudrate */
148 NULL, /* setstopbits */
149 NULL, /* setparity */
150 NULL, /* drain_output */
151 NULL, /* async */
152 NULL, /* read_prim */
153 NULL, /* write_prim */
154 NULL, /* avail */
155 #ifdef USE_WIN32API
156 serial_event_wait_handle,
157 #endif
158 };
159
160 /* See ser-event.h. */
161
162 struct serial_event *
163 make_serial_event (void)
164 {
165 return (struct serial_event *) serial_open_ops (&serial_event_ops);
166 }
167
168 /* See ser-event.h. */
169
170 int
171 serial_event_fd (struct serial_event *event)
172 {
173 struct serial *ser = (struct serial *) event;
174
175 return ser->fd;
176 }
177
178 /* See ser-event.h. */
179
180 void
181 serial_event_set (struct serial_event *event)
182 {
183 struct serial *ser = (struct serial *) event;
184 struct serial_event_state *state = (struct serial_event_state *) ser->state;
185 #ifndef USE_WIN32API
186 int r;
187 char c = '+'; /* Anything. */
188
189 do
190 {
191 r = write (state->write_fd, &c, 1);
192 }
193 while (r < 0 && errno == EINTR);
194 #else
195 SetEvent (state->event);
196 #endif
197 }
198
199 /* See ser-event.h. */
200
201 void
202 serial_event_clear (struct serial_event *event)
203 {
204 struct serial *ser = (struct serial *) event;
205 #ifndef USE_WIN32API
206 int r;
207
208 do
209 {
210 char c;
211
212 r = read (ser->fd, &c, 1);
213 }
214 while (r > 0 || (r < 0 && errno == EINTR));
215 #else
216 struct serial_event_state *state = (struct serial_event_state *) ser->state;
217 ResetEvent (state->event);
218 #endif
219 }