comparison src/event-unixoid.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 8de8e3f6228a
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /* Code shared between all event loops that use select() and have a
2 different input descriptor for each device.
3 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4 Copyright (C) 1995 Board of Trustees, University of Illinois.
5 Copyright (C) 1995 Sun Microsystems, Inc.
6 Copyright (C) 1995, 1996 Ben Wing.
7
8 This file is part of XEmacs.
9
10 XEmacs is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2, or (at your option) any
13 later version.
14
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with XEmacs; see the file COPYING. If not, write to
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 /* Synched up with: Not in FSF. */
26
27 /* This file has been Mule-ized. */
28
29 #include <config.h>
30 #include "lisp.h"
31
32 #include "console-stream.h"
33 #include "console-tty.h"
34 #include "device.h"
35 #include "events.h"
36 #include "lstream.h"
37 #include "process.h"
38
39 #include "sysdep.h"
40 #include "sysfile.h"
41 #include "sysproc.h" /* select stuff */
42 #include "systime.h"
43
44 /* Mask of bits indicating the descriptors that we wait for input on.
45 These work as follows:
46
47 input_wait_mask == mask of all file descriptors we select() on,
48 including TTY/stream console descriptors,
49 process descriptors, and the signal event pipe.
50 Only used in event-tty.c; event-Xt.c uses
51 XtAppAddInput(), and the call to select() is down in
52 the guts of Xt.
53
54 non_fake_input_wait_mask == same as input_wait_mask but minus the
55 signal event pipe. Also only used in
56 event-tty.c.
57
58 process_only_mask == only the process descriptors.
59
60 tty_only_mask == only the TTY/stream console descriptors.
61 */
62 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
63 SELECT_TYPE process_only_mask, tty_only_mask;
64
65 /* This is used to terminate the select(), when an event came in
66 through a signal (e.g. window-change or C-g on controlling TTY). */
67 int signal_event_pipe[2];
68
69 int signal_event_pipe_initialized;
70
71 int fake_event_occurred;
72
73 int
74 read_event_from_tty_or_stream_desc (struct Lisp_Event *event,
75 struct console *con, int fd)
76 {
77 unsigned char ch;
78 int nread;
79 Lisp_Object console;
80
81 XSETCONSOLE (console, con);
82
83 nread = read (fd, &ch, 1);
84 if (nread <= 0)
85 {
86 /* deleting the console might not be safe right now ... */
87 enqueue_magic_eval_event (io_error_delete_console, console);
88 /* but we definitely need to unselect it to avoid infinite
89 loops reading EOF's */
90 Fconsole_disable_input (console);
91 }
92 else
93 {
94 character_to_event (ch, event, con, 1, 1);
95 event->channel = console;
96 return 1;
97 }
98 return 0;
99 }
100
101 void
102 signal_fake_event (void)
103 {
104 char byte = 0;
105 /* We do the write always. Formerly I tried to "optimize" this
106 by setting a flag indicating whether we're blocking and only
107 doing the write in that case, but there is a race condition
108 if the signal occurs after we've checked for the signal
109 occurrence (which could occur in many places throughout
110 an iteration of the command loop, e.g. in status_notify()),
111 but before we set the blocking flag.
112
113 This should be OK as long as write() is reentrant, which
114 I'm fairly sure it is since it's a system call. */
115
116 if (signal_event_pipe_initialized)
117 /* In case a signal comes through while we're dumping */
118 {
119 int old_errno = errno;
120 write (signal_event_pipe[1], &byte, 1);
121 errno = old_errno;
122 }
123 }
124
125 void
126 drain_signal_event_pipe (void)
127 {
128 char chars[128];
129 /* The input end of the pipe has been set to non-blocking. */
130 while (read (signal_event_pipe[0], chars, sizeof (chars)) > 0)
131 ;
132 }
133
134 int
135 event_stream_unixoid_select_console (struct console *con)
136 {
137 int infd;
138
139 if (CONSOLE_STREAM_P (con))
140 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
141 else
142 {
143 assert (CONSOLE_TTY_P (con));
144 infd = CONSOLE_TTY_DATA (con)->infd;
145 }
146
147 assert (infd >= 0);
148
149 FD_SET (infd, &input_wait_mask);
150 FD_SET (infd, &non_fake_input_wait_mask);
151 FD_SET (infd, &tty_only_mask);
152 return infd;
153 }
154
155 int
156 event_stream_unixoid_unselect_console (struct console *con)
157 {
158 int infd;
159
160 if (CONSOLE_STREAM_P (con))
161 infd = fileno (CONSOLE_STREAM_DATA (con)->in);
162 else
163 {
164 assert (CONSOLE_TTY_P (con));
165 infd = CONSOLE_TTY_DATA (con)->infd;
166 }
167
168 assert (infd >= 0);
169
170 FD_CLR (infd, &input_wait_mask);
171 FD_CLR (infd, &non_fake_input_wait_mask);
172 FD_CLR (infd, &tty_only_mask);
173 return infd;
174 }
175
176 static int
177 get_process_infd (struct Lisp_Process *p)
178 {
179 Lisp_Object instr, outstr;
180 get_process_streams (p, &instr, &outstr);
181 assert (!NILP (instr));
182 return filedesc_stream_fd (XLSTREAM (instr));
183 }
184
185 int
186 event_stream_unixoid_select_process (struct Lisp_Process *proc)
187 {
188 int infd = get_process_infd (proc);
189
190 FD_SET (infd, &input_wait_mask);
191 FD_SET (infd, &non_fake_input_wait_mask);
192 FD_SET (infd, &process_only_mask);
193 return infd;
194 }
195
196 int
197 event_stream_unixoid_unselect_process (struct Lisp_Process *proc)
198 {
199 int infd = get_process_infd (proc);
200
201 FD_CLR (infd, &input_wait_mask);
202 FD_CLR (infd, &non_fake_input_wait_mask);
203 FD_CLR (infd, &process_only_mask);
204 return infd;
205 }
206
207 int
208 poll_fds_for_input (SELECT_TYPE mask)
209 {
210 EMACS_TIME sometime;
211 EMACS_SELECT_TIME select_time;
212 SELECT_TYPE temp_mask;
213 int retval;
214
215 while (1)
216 {
217 EMACS_SET_SECS_USECS (sometime, 0, 0);
218 EMACS_TIME_TO_SELECT_TIME (sometime, select_time);
219 temp_mask = mask;
220 /* To effect a poll, tell select() to block for zero seconds. */
221 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time);
222 if (retval >= 0)
223 return retval;
224 if (errno != EINTR)
225 {
226 /* Something went seriously wrong; don't abort since maybe
227 the TTY just died at the wrong time. */
228 fprintf (stderr, "xemacs: select failed: errno = %d\n", errno);
229 return 0;
230 }
231 /* else, we got interrupted by a signal, so try again. */
232 }
233
234 RETURN_NOT_REACHED(0) /* not reached */
235 }
236
237 /****************************************************************************/
238 /* Unixoid (file descriptors based) process I/O streams routines */
239 /****************************************************************************/
240
241 USID
242 event_stream_unixoid_create_stream_pair (void* inhandle, void* outhandle,
243 Lisp_Object* instream,
244 Lisp_Object* outstream,
245 int flags)
246 {
247 int infd, outfd;
248 /* Decode inhandle and outhandle. Their meaning depends on
249 the process implementation being used. */
250 #if defined (HAVE_WIN32_PROCESSES)
251 /* We're passed in Windows handles. Open new fds for them */
252 if ((HANDLE)inhandle != INVALID_HANDLE_VALUE)
253 {
254 infd = open_osfhandle ((HANDLE)inhandle, 0);
255 if (infd < 0)
256 return USID_ERROR;
257 }
258 else
259 infd = -1;
260
261 if ((HANDLE)outhandle != INVALID_HANDLE_VALUE)
262 {
263 outfd = open_osfhandle ((HANDLE)outhandle, 0);
264 if (outfd < 0)
265 {
266 if (infd >= 0)
267 close (infd);
268 return USID_ERROR;
269 }
270 }
271 else
272 outfd = -1;
273
274 flags = 0;
275 #elif defined (HAVE_UNIX_PROCESSES)
276 /* We are passed plain old file descs */
277 infd = (int)inhandle;
278 outfd = (int)outhandle;
279 #else
280 # error Which processes do you have?
281 #endif
282
283 *instream = (infd >= 0
284 ? make_filedesc_input_stream (infd, 0, -1, 0)
285 : Qnil);
286
287 *outstream = (outfd >= 0
288 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK)
289 : Qnil);
290
291 #if defined(HAVE_UNIX_PROCESSES) && defined(HAVE_PTYS)
292 /* FLAGS is process->pty_flag for UNIX_PROCESSES */
293 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0)
294 {
295 Bufbyte eof_char = get_eof_char (outfd);
296 int pty_max_bytes = get_pty_max_bytes (outfd);
297 filedesc_stream_set_pty_flushing (XLSTREAM(*outstream), pty_max_bytes, eof_char);
298 }
299 #endif
300
301 return FD_TO_USID (infd);
302 }
303
304 USID
305 event_stream_unixoid_delete_stream_pair (Lisp_Object instream,
306 Lisp_Object outstream)
307 {
308 int in = (NILP(instream) ? -1
309 : filedesc_stream_fd (XLSTREAM (instream)));
310 int out = (NILP(outstream) ? -1
311 : filedesc_stream_fd (XLSTREAM (outstream)));
312
313 if (in >= 0)
314 close (in);
315 if (out != in && out >= 0)
316 close (out);
317
318 return FD_TO_USID (in);
319 }
320
321
322 void
323 init_event_unixoid (void)
324 {
325 /* Do this first; the init_event_*_late() functions
326 pay attention to it. */
327 if (pipe (signal_event_pipe) < 0)
328 {
329 perror ("XEmacs: can't open pipe");
330 exit (-1);
331 }
332 signal_event_pipe_initialized = 1;
333
334 /* Set it non-blocking so we can drain its output. */
335 set_descriptor_non_blocking (signal_event_pipe[0]);
336
337 /* Also set the write descriptor non-blocking so we don't
338 hang in case a long time passes between times when
339 we drain the pipe. */
340 set_descriptor_non_blocking (signal_event_pipe[1]);
341
342 /* WARNING: In order for the signal-event pipe to work correctly
343 and not cause lockups, the following need to be followed:
344
345 1) event_pending_p() must ignore input on the signal-event pipe.
346 2) As soon as next_event() notices input on the signal-event
347 pipe, it must drain it. */
348 FD_ZERO (&input_wait_mask);
349 FD_ZERO (&non_fake_input_wait_mask);
350 FD_ZERO (&process_only_mask);
351 FD_ZERO (&tty_only_mask);
352
353 FD_SET (signal_event_pipe[0], &input_wait_mask);
354 }