comparison src/event-unixoid.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 25f70ba0133c
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
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 "process.h"
37
38 #include "sysdep.h"
39 #include "sysproc.h" /* select stuff */
40 #include "systime.h"
41
42 /* Mask of bits indicating the descriptors that we wait for input on.
43 These work as follows:
44
45 input_wait_mask == mask of all file descriptors we select() on,
46 including TTY/stream console descriptors,
47 process descriptors, and the signal event pipe.
48 Only used in event-tty.c; event-Xt.c uses
49 XtAppAddInput(), and the call to select() is down in
50 the guts of Xt.
51
52 non_fake_input_wait_mask == same as input_wait_mask but minus the
53 signal event pipe. Also only used in
54 event-tty.c.
55
56 process_only_mask == only the process descriptors.
57
58 tty_only_mask == only the TTY/stream console descriptors.
59 */
60 SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
61 SELECT_TYPE process_only_mask, tty_only_mask;
62
63 /* This is used to terminate the select(), when an event came in
64 through a signal (e.g. window-change or C-g on controlling TTY). */
65 int signal_event_pipe[2];
66
67 static int signal_event_pipe_initialized;
68
69 int fake_event_occurred;
70
71 int
72 read_event_from_tty_or_stream_desc (struct Lisp_Event *event,
73 struct console *con, int fd)
74 {
75 unsigned char ch;
76 int nread;
77 Lisp_Object console = Qnil;
78
79 XSETCONSOLE (console, con);
80
81 nread = read (fd, &ch, 1);
82 if (nread <= 0)
83 {
84 /* deleting the console might not be safe right now ... */
85 enqueue_magic_eval_event (io_error_delete_console, console);
86 /* but we definitely need to unselect it to avoid infinite
87 loops reading EOF's */
88 Fconsole_disable_input (console);
89 }
90 else
91 {
92 character_to_event (ch, event, con, 1);
93 event->channel = console;
94 return 1;
95 }
96 return 0;
97 }
98
99 void
100 signal_fake_event (void)
101 {
102 char byte = 0;
103 /* We do the write always. Formerly I tried to "optimize" this
104 by setting a flag indicating whether we're blocking and only
105 doing the write in that case, but there is a race condition
106 if the signal occurs after we've checked for the signal
107 occurrence (which could occur in many places throughout
108 an iteration of the command loop, e.g. in status_notify()),
109 but before we set the blocking flag.
110
111 This should be OK as long as write() is reentrant, which
112 I'm fairly sure it is since it's a system call. */
113
114 if (signal_event_pipe_initialized)
115 /* In case a signal comes through while we're dumping */
116 {
117 int old_errno = errno;
118 write (signal_event_pipe[1], &byte, 1);
119 errno = old_errno;
120 }
121 }
122
123 void
124 drain_signal_event_pipe (void)
125 {
126 char chars[128];
127 /* The input end of the pipe has been set to non-blocking. */
128 while (read (signal_event_pipe[0], chars, sizeof (chars)) > 0)
129 ;
130 }
131
132 int
133 event_stream_unixoid_select_console (struct console *con)
134 {
135 int infd;
136
137 if (CONSOLE_STREAM_P (con))
138 infd = fileno (CONSOLE_STREAM_DATA (con)->infd);
139 else
140 {
141 assert (CONSOLE_TTY_P (con));
142 infd = CONSOLE_TTY_DATA (con)->infd;
143 }
144
145 assert (infd >= 0);
146
147 FD_SET (infd, &input_wait_mask);
148 FD_SET (infd, &non_fake_input_wait_mask);
149 FD_SET (infd, &tty_only_mask);
150 return infd;
151 }
152
153 int
154 event_stream_unixoid_unselect_console (struct console *con)
155 {
156 int infd;
157
158 if (CONSOLE_STREAM_P (con))
159 infd = fileno (CONSOLE_STREAM_DATA (con)->infd);
160 else
161 {
162 assert (CONSOLE_TTY_P (con));
163 infd = CONSOLE_TTY_DATA (con)->infd;
164 }
165
166 assert (infd >= 0);
167
168 FD_CLR (infd, &input_wait_mask);
169 FD_CLR (infd, &non_fake_input_wait_mask);
170 FD_CLR (infd, &tty_only_mask);
171 return infd;
172 }
173
174 int
175 event_stream_unixoid_select_process (struct Lisp_Process *proc)
176 {
177 int infd, outfd;
178
179 get_process_file_descriptors (proc, &infd, &outfd);
180 assert (infd >= 0);
181
182 FD_SET (infd, &input_wait_mask);
183 FD_SET (infd, &non_fake_input_wait_mask);
184 FD_SET (infd, &process_only_mask);
185 return infd;
186 }
187
188 int
189 event_stream_unixoid_unselect_process (struct Lisp_Process *proc)
190 {
191 int infd, outfd;
192
193 get_process_file_descriptors (proc, &infd, &outfd);
194 assert (infd >= 0);
195
196 FD_CLR (infd, &input_wait_mask);
197 FD_CLR (infd, &non_fake_input_wait_mask);
198 FD_CLR (infd, &process_only_mask);
199 return infd;
200 }
201
202 int
203 poll_fds_for_input (SELECT_TYPE mask)
204 {
205 EMACS_TIME sometime;
206 EMACS_SELECT_TIME select_time;
207 SELECT_TYPE temp_mask;
208 int retval;
209
210 while (1)
211 {
212 EMACS_SET_SECS_USECS (sometime, 0, 0);
213 EMACS_TIME_TO_SELECT_TIME (sometime, select_time);
214 temp_mask = mask;
215 /* To effect a poll, tell select() to block for zero seconds. */
216 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time);
217 if (retval >= 0)
218 return retval;
219 if (errno != EINTR)
220 {
221 /* Something went seriously wrong; don't abort since maybe
222 the TTY just died at the wrong time. */
223 fprintf (stderr, "xemacs: select failed: errno = %d\n", errno);
224 return 0;
225 }
226 /* else, we got interrupted by a signal, so try again. */
227 }
228
229 RETURN_NOT_REACHED(0) /* not reached */
230 }
231
232
233 void
234 init_event_unixoid (void)
235 {
236 /* Do this first; the init_event_*_late() functions
237 pay attention to it. */
238 if (pipe (signal_event_pipe) < 0)
239 {
240 perror ("XEmacs: can't open pipe");
241 exit (-1);
242 }
243 signal_event_pipe_initialized = 1;
244
245 /* Set it non-blocking so we can drain its output. */
246 set_descriptor_non_blocking (signal_event_pipe[0]);
247
248 /* Also set the write descriptor non-blocking so we don't
249 hang in case a long time passes between times when
250 we drain the pipe. */
251 set_descriptor_non_blocking (signal_event_pipe[1]);
252
253 /* WARNING: In order for the signal-event pipe to work correctly
254 and not cause lockups, the following need to be followed:
255
256 1) event_pending_p() must ignore input on the signal-event pipe.
257 2) As soon as next_event() notices input on the signal-event
258 pipe, it must drain it. */
259 FD_ZERO (&input_wait_mask);
260 FD_ZERO (&non_fake_input_wait_mask);
261 FD_ZERO (&process_only_mask);
262 FD_ZERO (&tty_only_mask);
263
264 FD_SET (signal_event_pipe[0], &input_wait_mask);
265 }