Mercurial > hg > xemacs-beta
annotate src/event-unixoid.c @ 5925:08cfc8f77fb6 cygwin
make space for long ptr, and store as such, for frame in WINDOW data,
add a bit more debugging to debug-mswindow,
Vin Shelton patch to fix M-x shell
| author | Henry Thompson <ht@markup.co.uk> |
|---|---|
| date | Fri, 27 Feb 2015 17:41:20 +0000 |
| parents | a216b3c2b09e |
| children |
| rev | line source |
|---|---|
| 428 | 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. | |
| 1268 | 6 Copyright (C) 1995, 1996, 2001, 2002, 2003 Ben Wing. |
| 428 | 7 |
| 8 This file is part of XEmacs. | |
| 9 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
10 XEmacs is free software: you can redistribute it and/or modify it |
| 428 | 11 under the terms of the GNU General Public License as published by the |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
12 Free Software Foundation, either version 3 of the License, or (at your |
|
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
13 option) any later version. |
| 428 | 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 | |
|
5402
308d34e9f07d
Changed bulk of GPLv2 or later files identified by script
Mats Lidell <matsl@xemacs.org>
parents:
5016
diff
changeset
|
21 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 428 | 22 |
| 23 /* Synched up with: Not in FSF. */ | |
| 24 | |
| 25 /* This file has been Mule-ized. */ | |
| 26 | |
| 27 #include <config.h> | |
| 28 #include "lisp.h" | |
| 29 | |
| 872 | 30 #include "console-stream-impl.h" |
| 31 #include "console-tty-impl.h" | |
| 1204 | 32 #include "device-impl.h" |
| 428 | 33 #include "events.h" |
| 34 #include "lstream.h" | |
| 35 #include "process.h" | |
| 36 | |
| 37 #include "sysdep.h" | |
| 38 #include "sysfile.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 | |
| 1268 | 45 In event-tty.c we call select() directly on this |
| 46 to retrieve an event. In event-Xt.c we use | |
| 47 XtAppAddInput() and the call to select() is down in | |
| 48 the guts of Xt, but we still use the masks when checking for pending input, even in event-Xt.c. (We can't use XtAppPending() because of the presence of the signal event pipe.) | |
| 49 | |
| 428 | 50 input_wait_mask == mask of all file descriptors we select() on, |
| 51 including TTY/stream console descriptors, | |
| 52 process descriptors, and the signal event pipe. | |
| 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 | |
| 1204 | 73 struct console * |
| 74 find_tty_or_stream_console_from_fd (int fd) | |
| 75 { | |
| 76 Lisp_Object concons; | |
| 77 | |
| 78 CONSOLE_LOOP (concons) | |
| 79 { | |
| 80 struct console *c; | |
| 81 | |
| 82 c = XCONSOLE (XCAR (concons)); | |
| 83 if ((CONSOLE_TTY_P (c) && CONSOLE_TTY_DATA (c)->infd == fd) || | |
| 84 (CONSOLE_STREAM_P (c) && fileno (CONSOLE_STREAM_DATA (c)->in) == fd)) | |
| 85 return c; | |
| 86 } | |
| 87 | |
| 88 return 0; | |
| 89 } | |
| 90 | |
| 428 | 91 int |
| 771 | 92 read_event_from_tty_or_stream_desc (Lisp_Event *event, struct console *con) |
| 428 | 93 { |
| 867 | 94 Ichar ch; |
| 793 | 95 Lisp_Object console = wrap_console (con); |
| 428 | 96 |
| 771 | 97 if (CONSOLE_TTY_P (con)) |
| 867 | 98 ch = Lstream_get_ichar (XLSTREAM (CONSOLE_TTY_DATA (con)->instream)); |
| 771 | 99 else |
| 100 { | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
101 Ibyte ibyte; |
| 771 | 102 /* #### Definitely something strange here. We should be setting |
| 103 the stdio handle unbuffered and reading from it instead of mixing | |
| 104 stdio and raw io calls. */ | |
|
4954
70e8a00896e9
fix an obscure crash reading from stream devices
Ben Wing <ben@xemacs.org>
parents:
4780
diff
changeset
|
105 int nread = retry_read (fileno (CONSOLE_STREAM_DATA (con)->in), |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
106 &ibyte, 1); |
| 771 | 107 if (nread <= 0) |
| 108 ch = -1; | |
|
4954
70e8a00896e9
fix an obscure crash reading from stream devices
Ben Wing <ben@xemacs.org>
parents:
4780
diff
changeset
|
109 else |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
110 ch = ibyte; |
| 771 | 111 } |
| 112 | |
| 113 if (ch < 0) | |
| 428 | 114 { |
| 115 /* deleting the console might not be safe right now ... */ | |
| 116 enqueue_magic_eval_event (io_error_delete_console, console); | |
| 117 /* but we definitely need to unselect it to avoid infinite | |
| 118 loops reading EOF's */ | |
| 119 Fconsole_disable_input (console); | |
| 120 } | |
| 121 else | |
| 122 { | |
|
4780
2fd201d73a92
Call character_to_event on characters received from XIM, event-Xt.c
Aidan Kehoe <kehoea@parhasard.net>
parents:
4031
diff
changeset
|
123 character_to_event (ch, event, con, use_console_meta_flag, 1); |
| 428 | 124 event->channel = console; |
| 125 return 1; | |
| 126 } | |
| 127 return 0; | |
| 128 } | |
| 129 | |
| 130 void | |
| 131 signal_fake_event (void) | |
| 132 { | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
133 Rawbyte rbyte = 0; |
| 428 | 134 /* We do the write always. Formerly I tried to "optimize" this |
| 135 by setting a flag indicating whether we're blocking and only | |
| 136 doing the write in that case, but there is a race condition | |
| 137 if the signal occurs after we've checked for the signal | |
| 138 occurrence (which could occur in many places throughout | |
| 139 an iteration of the command loop, e.g. in status_notify()), | |
| 140 but before we set the blocking flag. | |
| 141 | |
| 771 | 142 This should be OK as long as write() is reentrant, which I'm fairly |
| 143 sure it is since it's a system call. */ | |
| 428 | 144 |
| 145 if (signal_event_pipe_initialized) | |
| 146 /* In case a signal comes through while we're dumping */ | |
| 147 { | |
| 148 int old_errno = errno; | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
149 retry_write (signal_event_pipe[1], &rbyte, 1); |
| 428 | 150 errno = old_errno; |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void | |
| 155 drain_signal_event_pipe (void) | |
| 156 { | |
|
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4954
diff
changeset
|
157 Rawbyte chars[128]; |
| 428 | 158 /* The input end of the pipe has been set to non-blocking. */ |
| 771 | 159 while (retry_read (signal_event_pipe[0], chars, sizeof (chars)) > 0) |
| 428 | 160 ; |
| 161 } | |
| 162 | |
| 1204 | 163 void |
| 164 drain_tty_devices (void) | |
| 165 { | |
| 166 Lisp_Object devcons, concons; | |
| 167 CONSOLE_LOOP (concons) | |
| 168 { | |
| 169 struct console *con = XCONSOLE (XCAR (concons)); | |
| 170 if (!con->input_enabled) | |
| 171 continue; | |
| 172 | |
| 173 CONSOLE_DEVICE_LOOP (devcons, con) | |
| 174 { | |
| 175 struct device *d = XDEVICE (XCAR (devcons)); | |
| 176 if (DEVICE_TTY_P (d)) | |
| 177 { | |
| 178 SELECT_TYPE temp_mask; | |
| 179 int infd = DEVICE_INFD (d); | |
| 180 | |
| 181 FD_ZERO (&temp_mask); | |
| 182 FD_SET (infd, &temp_mask); | |
| 183 | |
| 184 while (1) | |
| 185 { | |
| 186 Lisp_Object event; | |
| 187 | |
| 188 if (!poll_fds_for_input (temp_mask)) | |
| 189 break; | |
| 190 | |
| 191 event = Fmake_event (Qnil, Qnil); | |
| 192 if (!read_event_from_tty_or_stream_desc (XEVENT (event), | |
| 193 con)) | |
| 194 /* EOF, or something ... */ | |
| 195 break; | |
| 196 | |
| 197 /* queue the read event to be read for real later. */ | |
| 198 enqueue_dispatch_event (event); | |
| 199 } | |
| 200 } | |
| 201 } | |
| 202 } | |
| 203 } | |
| 204 | |
| 428 | 205 int |
| 206 event_stream_unixoid_select_console (struct console *con) | |
| 207 { | |
| 208 int infd; | |
| 209 | |
| 210 if (CONSOLE_STREAM_P (con)) | |
| 211 infd = fileno (CONSOLE_STREAM_DATA (con)->in); | |
| 212 else | |
| 213 { | |
| 214 assert (CONSOLE_TTY_P (con)); | |
| 215 infd = CONSOLE_TTY_DATA (con)->infd; | |
| 216 } | |
| 217 | |
| 218 assert (infd >= 0); | |
| 219 | |
| 220 FD_SET (infd, &input_wait_mask); | |
| 221 FD_SET (infd, &non_fake_input_wait_mask); | |
| 222 FD_SET (infd, &tty_only_mask); | |
| 223 return infd; | |
| 224 } | |
| 225 | |
| 226 int | |
| 227 event_stream_unixoid_unselect_console (struct console *con) | |
| 228 { | |
| 229 int infd; | |
| 230 | |
| 231 if (CONSOLE_STREAM_P (con)) | |
| 232 infd = fileno (CONSOLE_STREAM_DATA (con)->in); | |
| 233 else | |
| 234 { | |
| 235 assert (CONSOLE_TTY_P (con)); | |
| 236 infd = CONSOLE_TTY_DATA (con)->infd; | |
| 237 } | |
| 238 | |
| 239 assert (infd >= 0); | |
| 240 | |
| 241 FD_CLR (infd, &input_wait_mask); | |
| 242 FD_CLR (infd, &non_fake_input_wait_mask); | |
| 243 FD_CLR (infd, &tty_only_mask); | |
| 244 return infd; | |
| 245 } | |
| 246 | |
| 247 static int | |
| 440 | 248 get_process_infd (Lisp_Process *p) |
| 428 | 249 { |
| 853 | 250 Lisp_Object instr, outstr, errstr; |
| 251 get_process_streams (p, &instr, &outstr, &errstr); | |
| 428 | 252 assert (!NILP (instr)); |
| 253 return filedesc_stream_fd (XLSTREAM (instr)); | |
| 254 } | |
| 255 | |
| 853 | 256 static int |
| 257 get_process_errfd (Lisp_Process *p) | |
| 428 | 258 { |
| 853 | 259 Lisp_Object instr, outstr, errstr; |
| 260 get_process_streams (p, &instr, &outstr, &errstr); | |
| 261 if (!NILP (errstr)) | |
| 262 return filedesc_stream_fd (XLSTREAM (errstr)); | |
| 263 else | |
| 264 return -1; | |
| 428 | 265 } |
| 266 | |
| 853 | 267 void |
| 268 event_stream_unixoid_select_process (Lisp_Process *proc, int doin, int doerr, | |
| 269 int *infd, int *errfd) | |
| 428 | 270 { |
| 853 | 271 if (doin) |
| 272 { | |
| 273 *infd = get_process_infd (proc); | |
| 274 FD_SET (*infd, &input_wait_mask); | |
| 275 FD_SET (*infd, &non_fake_input_wait_mask); | |
| 276 FD_SET (*infd, &process_only_mask); | |
| 277 } | |
| 278 | |
| 279 if (doerr) | |
| 280 { | |
| 281 *errfd = get_process_errfd (proc); | |
| 428 | 282 |
| 853 | 283 if (*errfd >= 0) |
| 284 { | |
| 285 FD_SET (*errfd, &input_wait_mask); | |
| 286 FD_SET (*errfd, &non_fake_input_wait_mask); | |
| 287 FD_SET (*errfd, &process_only_mask); | |
| 288 } | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 void | |
| 293 event_stream_unixoid_unselect_process (Lisp_Process *proc, int doin, int doerr, | |
| 294 int *infd, int *errfd) | |
| 295 { | |
| 296 if (doin) | |
| 297 { | |
| 298 *infd = get_process_infd (proc); | |
| 299 FD_CLR (*infd, &input_wait_mask); | |
| 300 FD_CLR (*infd, &non_fake_input_wait_mask); | |
| 301 FD_CLR (*infd, &process_only_mask); | |
| 302 } | |
| 303 | |
| 304 if (doerr) | |
| 305 { | |
| 306 *errfd = get_process_errfd (proc); | |
| 307 | |
| 308 if (*errfd >= 0) | |
| 309 { | |
| 310 FD_CLR (*errfd, &input_wait_mask); | |
| 311 FD_CLR (*errfd, &non_fake_input_wait_mask); | |
| 312 FD_CLR (*errfd, &process_only_mask); | |
| 313 } | |
| 314 } | |
| 428 | 315 } |
| 316 | |
| 317 int | |
| 318 poll_fds_for_input (SELECT_TYPE mask) | |
| 319 { | |
| 320 EMACS_TIME sometime; | |
| 321 EMACS_SELECT_TIME select_time; | |
| 322 SELECT_TYPE temp_mask; | |
| 323 int retval; | |
| 324 | |
| 325 while (1) | |
| 326 { | |
| 327 EMACS_SET_SECS_USECS (sometime, 0, 0); | |
| 328 EMACS_TIME_TO_SELECT_TIME (sometime, select_time); | |
| 329 temp_mask = mask; | |
| 330 /* To effect a poll, tell select() to block for zero seconds. */ | |
| 331 retval = select (MAXDESC, &temp_mask, 0, 0, &select_time); | |
| 332 if (retval >= 0) | |
| 333 return retval; | |
| 334 if (errno != EINTR) | |
| 335 { | |
| 336 /* Something went seriously wrong; don't abort since maybe | |
| 337 the TTY just died at the wrong time. */ | |
| 442 | 338 stderr_out ("xemacs: select failed: errno = %d\n", errno); |
| 428 | 339 return 0; |
| 340 } | |
| 341 /* else, we got interrupted by a signal, so try again. */ | |
| 342 } | |
| 343 | |
| 1204 | 344 RETURN_NOT_REACHED (0); |
| 428 | 345 } |
| 346 | |
| 347 /****************************************************************************/ | |
| 348 /* Unixoid (file descriptors based) process I/O streams routines */ | |
| 349 /****************************************************************************/ | |
| 350 | |
| 853 | 351 void |
| 352 event_stream_unixoid_create_io_streams (void* inhandle, void* outhandle, | |
| 353 void *errhandle, Lisp_Object* instream, | |
| 354 Lisp_Object* outstream, | |
| 355 Lisp_Object* errstream, | |
| 356 USID* in_usid, | |
| 357 USID* err_usid, | |
| 358 int flags) | |
| 428 | 359 { |
|
5814
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
360 tls_state_t *tls_state; |
| 853 | 361 int infd, outfd, errfd; |
| 428 | 362 /* Decode inhandle and outhandle. Their meaning depends on |
| 363 the process implementation being used. */ | |
| 4031 | 364 /* We are passed plain old file descs, which are ints, so */ |
| 365 /* if sizeof(EMACS_INT) > sizeof(int) it's OK. */ | |
| 366 infd = (EMACS_INT) inhandle; | |
| 367 outfd = (EMACS_INT) outhandle; | |
| 368 errfd = (EMACS_INT) errhandle; | |
| 428 | 369 |
|
5814
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
370 tls_state = (flags & STREAM_USE_TLS) ? (tls_state_t *) inhandle : NULL; |
|
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
371 |
| 428 | 372 *instream = (infd >= 0 |
|
5814
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
373 ? make_filedesc_input_stream (infd, 0, -1, |
|
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
374 tls_state ? LSTR_BLOCKED_OK : 0, |
|
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
375 tls_state) |
| 428 | 376 : Qnil); |
| 377 | |
| 378 *outstream = (outfd >= 0 | |
|
5814
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
379 ? make_filedesc_output_stream (outfd, 0, -1, LSTR_BLOCKED_OK, |
|
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
380 tls_state) |
| 428 | 381 : Qnil); |
| 382 | |
| 853 | 383 *errstream = (errfd >= 0 |
|
5814
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
384 ? make_filedesc_input_stream (errfd, 0, -1, 0, tls_state) |
|
a216b3c2b09e
Add TLS support. See xemacs-patches message with ID
Jerry James <james@xemacs.org>
parents:
5402
diff
changeset
|
385 : Qnil); |
| 853 | 386 |
| 428 | 387 /* FLAGS is process->pty_flag for UNIX_PROCESSES */ |
| 388 if ((flags & STREAM_PTY_FLUSHING) && outfd >= 0) | |
| 389 { | |
| 867 | 390 Ibyte eof_char = get_eof_char (outfd); |
| 428 | 391 int pty_max_bytes = get_pty_max_bytes (outfd); |
| 853 | 392 filedesc_stream_set_pty_flushing (XLSTREAM (*outstream), pty_max_bytes, |
| 393 eof_char); | |
| 428 | 394 } |
| 395 | |
| 853 | 396 *in_usid = FD_TO_USID (infd); |
| 397 *err_usid = FD_TO_USID (errfd); | |
| 428 | 398 } |
| 399 | |
| 853 | 400 void |
| 401 event_stream_unixoid_delete_io_streams (Lisp_Object instream, | |
| 402 Lisp_Object outstream, | |
| 403 Lisp_Object errstream, | |
| 404 USID *in_usid, | |
| 405 USID *err_usid) | |
| 428 | 406 { |
| 853 | 407 int in = (NILP (instream) ? -1 |
| 428 | 408 : filedesc_stream_fd (XLSTREAM (instream))); |
| 853 | 409 int out = (NILP (outstream) ? -1 |
| 428 | 410 : filedesc_stream_fd (XLSTREAM (outstream))); |
| 853 | 411 int err = (NILP (errstream) ? -1 |
| 412 : filedesc_stream_fd (XLSTREAM (errstream))); | |
| 428 | 413 |
| 414 if (in >= 0) | |
| 771 | 415 retry_close (in); |
| 428 | 416 if (out != in && out >= 0) |
| 771 | 417 retry_close (out); |
| 853 | 418 if (err != in && err != out && err >= 0) |
| 419 retry_close (err); | |
| 428 | 420 |
| 853 | 421 *in_usid = FD_TO_USID (in); |
| 422 *err_usid = FD_TO_USID (err); | |
| 428 | 423 } |
| 424 | |
| 425 | |
| 426 void | |
| 427 init_event_unixoid (void) | |
| 428 { | |
| 429 /* Do this first; the init_event_*_late() functions | |
| 430 pay attention to it. */ | |
| 431 if (pipe (signal_event_pipe) < 0) | |
| 432 { | |
| 433 perror ("XEmacs: can't open pipe"); | |
| 434 exit (-1); | |
| 435 } | |
| 436 signal_event_pipe_initialized = 1; | |
| 437 | |
| 438 /* Set it non-blocking so we can drain its output. */ | |
| 439 set_descriptor_non_blocking (signal_event_pipe[0]); | |
| 440 | |
| 441 /* Also set the write descriptor non-blocking so we don't | |
| 442 hang in case a long time passes between times when | |
| 443 we drain the pipe. */ | |
| 444 set_descriptor_non_blocking (signal_event_pipe[1]); | |
| 445 | |
| 446 /* WARNING: In order for the signal-event pipe to work correctly | |
| 447 and not cause lockups, the following need to be followed: | |
| 448 | |
| 449 1) event_pending_p() must ignore input on the signal-event pipe. | |
| 450 2) As soon as next_event() notices input on the signal-event | |
| 451 pipe, it must drain it. */ | |
| 452 FD_ZERO (&input_wait_mask); | |
| 453 FD_ZERO (&non_fake_input_wait_mask); | |
| 454 FD_ZERO (&process_only_mask); | |
| 455 FD_ZERO (&tty_only_mask); | |
| 456 | |
| 457 FD_SET (signal_event_pipe[0], &input_wait_mask); | |
| 458 } |
