Mercurial > hg > xemacs-beta
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 } |