From 2878ba7ef3225a7946c72ef6346467f35c453347 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 6 Aug 2013 07:17:25 -0700 Subject: * process.c: Fix minor off-by-one issues in descriptor counts. This shouldn't fix any real bugs, but it cleans up the code a bit. (max_process_desc, max_input_desc): -1, not 0, means none. All uses changed. (delete_input_desc): New function. (delete_write_fd, delete_keyboard_wait_descriptor): Use it. (deactivate_process): Scan backwards when recomuting max_process_desc; that should be faster. (init_process_emacs): Initialize max_input_desc. --- src/process.c | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index d87a1803fe2..85d07028c59 100644 --- a/src/process.c +++ b/src/process.c @@ -323,10 +323,10 @@ static SELECT_TYPE connect_wait_mask; static int num_pending_connects; #endif /* NON_BLOCKING_CONNECT */ -/* The largest descriptor currently in use for a process object. */ +/* The largest descriptor currently in use for a process object; -1 if none. */ static int max_process_desc; -/* The largest descriptor currently in use for input. */ +/* The largest descriptor currently in use for input; -1 if none. */ static int max_input_desc; /* Indexed by descriptor, gives the process (if any) for that descriptor */ @@ -500,13 +500,27 @@ add_write_fd (int fd, fd_callback func, void *data) fd_callback_info[fd].condition |= FOR_WRITE; } +/* FD is no longer an input descriptor; update max_input_desc accordingly. */ + +static void +delete_input_desc (int fd) +{ + if (fd == max_input_desc) + { + do + fd--; + while (0 <= fd && ! (FD_ISSET (fd, &input_wait_mask) + || FD_ISSET (fd, &write_mask))); + + max_input_desc = fd; + } +} + /* Stop monitoring file descriptor FD for when write is possible. */ void delete_write_fd (int fd) { - int lim = max_input_desc; - eassert (fd < MAXDESC); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; @@ -514,15 +528,7 @@ delete_write_fd (int fd) { fd_callback_info[fd].func = 0; fd_callback_info[fd].data = 0; - - if (fd == max_input_desc) - for (fd = lim; fd >= 0; fd--) - if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) - { - max_input_desc = fd; - break; - } - + delete_input_desc (fd); } } @@ -3831,13 +3837,14 @@ deactivate_process (Lisp_Object proc) #endif if (inchannel == max_process_desc) { - int i; /* We just closed the highest-numbered process input descriptor, so recompute the highest-numbered one now. */ - max_process_desc = 0; - for (i = 0; i < MAXDESC; i++) - if (!NILP (chan_process[i])) - max_process_desc = i; + int i = inchannel; + do + i--; + while (0 <= i && NILP (chan_process[i])); + + max_process_desc = i; } } } @@ -6763,16 +6770,9 @@ void delete_keyboard_wait_descriptor (int desc) { #ifdef subprocesses - int fd; - int lim = max_input_desc; - FD_CLR (desc, &input_wait_mask); FD_CLR (desc, &non_process_wait_mask); - - if (desc == max_input_desc) - for (fd = 0; fd < lim; fd++) - if (FD_ISSET (fd, &input_wait_mask) || FD_ISSET (fd, &write_mask)) - max_input_desc = fd; + delete_input_desc (desc); #endif } @@ -7037,7 +7037,7 @@ init_process_emacs (void) FD_ZERO (&non_keyboard_wait_mask); FD_ZERO (&non_process_wait_mask); FD_ZERO (&write_mask); - max_process_desc = 0; + max_process_desc = max_input_desc = -1; memset (fd_callback_info, 0, sizeof (fd_callback_info)); #ifdef NON_BLOCKING_CONNECT -- cgit v1.2.1 From 7d652d97681c4f1b67018f44f64c619ef5edd990 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 10 Aug 2013 18:30:20 -0700 Subject: Omit some unnecessary casts. Many of these go back to the old pre-C89 days, when they may have been needed, but we've been assuming C89 or later for a while now. * alloc.c (live_string_p, live_cons_p, live_symbol_p) (live_float_p, live_misc_p, live_vector_p): * buffer.c (compare_overlays, cmp_for_strings, mmap_find) (mmap_alloc, alloc_buffer_text, enlarge_buffer_text) (defvar_per_buffer): * callint.c (Fcall_interactively): * doc.c (Fsubstitute_command_keys): * filelock.c (get_boot_time): * frame.c (xrdb_get_resource): * gtkutil.c (hierarchy_ch_cb, qttip_cb, style_changed_cb) (delete_cb, xg_dialog_response_cb, xg_maybe_add_timer) (xg_get_file_name_from_selector, menuitem_destroy_callback) (menuitem_highlight_callback, menu_destroy_callback) (xg_update_menu_item, xg_modify_menubar_widgets, menubar_map_cb) (xg_tool_bar_callback, xg_get_tool_bar_widgets) (xg_tool_bar_detach_callback, xg_tool_bar_attach_callback) (xg_tool_bar_help_callback, tb_size_cb): * image.c (xpm_alloc_color, png_read_from_memory) (png_read_from_file, png_load_body, our_memory_skip_input_data) (jpeg_memory_src, jpeg_file_src, imagemagick_load_image) (syms_of_image): * keymap.c (describe_map): * nsfns.m (Fns_display_monitor_attributes_list): * nsmenu.m (process_dialog:): * nsterm.m (hold_event): * process.c (wait_reading_process_output): * regex.c (REGEX_REALLOCATE, re_set_registers, re_exec, regexec): * scroll.c (do_direct_scrolling, scrolling_1): * termcap.c (tgetent): * window.c (check_window_containing, add_window_to_list) (freeze_window_starts): * xdisp.c (compare_overlay_entries, vmessage): * xfns.c (x_window, x_get_monitor_attributes_xinerama) (x_get_monitor_attributes_xrandr) (Fx_display_monitor_attributes_list, x_display_info_for_name) (Fx_open_connection, file_dialog_cb, file_dialog_unmap_cb): * xfont.c (xfont_match, xfont_open): * xmenu.c (x_menu_wait_for_event, menu_highlight_callback) (menubar_selection_callback, menu_position_func) (popup_selection_callback, create_and_show_popup_menu) (dialog_selection_callback, create_and_show_dialog): * xrdb.c (x_get_string_resource): (main) [TESTRM]: * xsmfns.c (x_session_check_input): * xterm.c (x_draw_glyphless_glyph_string_foreground) (xm_scroll_callback, xg_scroll_callback, xg_end_scroll_callback) (xaw_jump_callback, xaw_scroll_callback): Omit unnecessary casts. --- src/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 85d07028c59..99c707ff97b 100644 --- a/src/process.c +++ b/src/process.c @@ -4526,7 +4526,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, #endif (max (max_process_desc, max_input_desc) + 1, &Available, - (check_write ? &Writeok : (SELECT_TYPE *)0), + (check_write ? &Writeok : 0), NULL, &timeout, NULL); #ifdef HAVE_GNUTLS -- cgit v1.2.1 From 94fcd171894e3a14d3548c028c4229229e32d184 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 12 Aug 2013 00:12:07 -0700 Subject: Fix some fd issues when running subprocesses. Fix bugs that can leak files or file descriptors on errors. Don't unlink open temp files, as that's hard for users to diagnose when things go awry (e.g., temp disk exhausted). Don't bother to lock temp files. Check for invalid recursion. * callproc.c (synch_process_fd): Remove. All uses removed. (synch_process_tempfile): New var or macro. (CALLPROC_STDOUT, CALLPROC_STDERR, CALLPROC_PIPEREAD, CALLPROC_FDS): New constants. (record_kill_process): New arg, the temp name. All callers changed. (delete_temp_file): Now just a simple wrapper around unlink. (call_process_kill): New arg, the call_process_fd array. Close them all. Clear synch_process_pid. Remove the temp file, or arrange for it to be removed. (call_process_cleanup) [MSDOS]: Arg no longer contains file name; that's been moved to synch_process_tempfile. Caller changed. Do not remove the tempfile; that's now call_process_kill's responsibility. (call_process_cleanup) [!MSDOS]: Do not record unwind-protect for call_process_kill; the caller now does that. (call_process_cleanup): Do not close the process fd; that's now call_process_kill's responsibility. (Fcall_process): Implement via new function call_process, which has most of the old body of Fcall_process, but with a different API. (call_process): New function that does not open or close filefd if it is nonnegative. Record which fds need to be closed, and let call_process_kill close (and remove the tempfile, on MSDOS) on error. Signal an error if invoked recursively (could be done via a hook). Simplify creation of the tempfile in the MSDOS case. Don't create the output file until after checking for the executable. Report any failure to open /dev/null. Don't open /dev/null for writing twice; once is enough. Don't create pipe if all output is being discarded or sent to file. Don't worry about setting up the coding system or reading from the pipe if all output is being discarded. Hoist fd_error local into top level, to lessen block nesting. Don't record deleted pid here; now done by Fcall_process_region. (Fcall_process) [MSDOS]: Report mktemp failure immediately, and note its success in synch_process_tempfile. Do not leak resources when child_setup fails. (Fcall_process) [!MSDOS && !WINDOWSNT]: Remove duplicate assignment to child_errno. Remove unnecessary close of fd0; it's close-on-exec. (create_temp_file): Now returns open fd, with an additional Lisp_Object * argument to return the name. All callers changed. Do not close the file; rewind it instead, and leave it open for the caller. Do not lock the temp file. Unwind-protect the file and the file-descriptor. (Fcall_process_region): If the input is /dev/null, unwind-protect it. If an asynchrounous process, record it here, not in call_process. (syms_of_callproc) [MSDOS]: Initialize synch_process_tempfile. * eval.c (set_unwind_protect): New function. * fileio.c (write_region): New function, generalized from the old Fwrite_region. Do not lock temp files. (Fwrite_region): Use it. * lisp.h (set_unwind_protect, write_region): New decls. * process.c: Include . (make_process): Mark fds as initially closed. (deleted_pid_list): Now a list of pid-filename pairs. All uses changed. (close_process_fd): New function. (SUBPROCESS_STDIN, WRITE_TO_SUBPROCESS, READ_FROM_SUBPROCESS) (SUBPROCESS_STDOUT, READ_FROM_EXEC_MONITOR, EXEC_MONITOR_OUTPUT): New constants. Verify that their number matches PROCESS_OPEN_FDS. (create_process, create_pty, Fmake_serial_process) (server_accept_connection): Record which fds need to be closed, and let deactivate_process close them. (Fmake_network_process): Do not discard the unwind-protect until it's safe to do so. (deactivate_process): Close the fds opened by create_process etc. (Fprocess_send_eof): Adjust to new way of recording open fds. Report an error if /dev/null can't be opened, instead of aborting. * process.h (PROCESS_OPEN_FDS): New constant. (struct Lisp_Process): New member open_fds. (record_kill_process, record_deleted_pid): Adjust signatures. (record_deleted_pid): Move decl here ... * syswait.h (record_deleted_pid): ... from here. Fixes: debbugs:15035 --- src/process.c | 225 +++++++++++++++++++++++++++++++++------------------------- 1 file changed, 127 insertions(+), 98 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 99c707ff97b..a2bcffe5160 100644 --- a/src/process.c +++ b/src/process.c @@ -92,6 +92,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #endif /* subprocesses */ @@ -722,6 +723,8 @@ make_process (Lisp_Object name) non-Lisp data, so do it only for slots which should not be zero. */ p->infd = -1; p->outfd = -1; + for (i = 0; i < PROCESS_OPEN_FDS; i++) + p->open_fd[i] = -1; #ifdef HAVE_GNUTLS p->gnutls_initstage = GNUTLS_STAGE_EMPTY; @@ -818,13 +821,17 @@ get_process (register Lisp_Object name) treated by the SIGCHLD handler and waitpid has been invoked on them; otherwise they might fill up the kernel's process table. - Some processes created by call-process are also put onto this list. */ + Some processes created by call-process are also put onto this list. + + Members of this list are (process-ID . filename) pairs. The + process-ID is a number; the filename, if a string, is a file that + needs to be removed after the process exits. */ static Lisp_Object deleted_pid_list; void -record_deleted_pid (pid_t pid) +record_deleted_pid (pid_t pid, Lisp_Object filename) { - deleted_pid_list = Fcons (make_fixnum_or_float (pid), + deleted_pid_list = Fcons (Fcons (make_fixnum_or_float (pid), filename), /* GC treated elements set to nil. */ Fdelq (Qnil, deleted_pid_list)); @@ -852,7 +859,7 @@ nil, indicating the current buffer's process. */) else { if (p->alive) - record_kill_process (p); + record_kill_process (p, Qnil); if (p->infd >= 0) { @@ -1605,17 +1612,45 @@ start_process_unwind (Lisp_Object proc) remove_process (proc); } +/* If *FD_ADDR is nonnegative, close it, and mark it as closed. */ + +static void +close_process_fd (int *fd_addr) +{ + int fd = *fd_addr; + if (0 <= fd) + { + *fd_addr = -1; + emacs_close (fd); + } +} + +/* Indexes of file descriptors in open_fds. */ +enum + { + /* The pipe from Emacs to its subprocess. */ + SUBPROCESS_STDIN, + WRITE_TO_SUBPROCESS, + + /* The main pipe from the subprocess to Emacs. */ + READ_FROM_SUBPROCESS, + SUBPROCESS_STDOUT, + + /* The pipe from the subprocess to Emacs that is closed when the + subprocess execs. */ + READ_FROM_EXEC_MONITOR, + EXEC_MONITOR_OUTPUT + }; + +verify (PROCESS_OPEN_FDS == EXEC_MONITOR_OUTPUT + 1); static void create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) { + struct Lisp_Process *p = XPROCESS (process); int inchannel, outchannel; pid_t pid; int vfork_errno; - int sv[2]; -#ifndef WINDOWSNT - int wait_child_setup[2]; -#endif int forkin, forkout; bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; @@ -1629,6 +1664,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (inchannel >= 0) { + p->open_fd[READ_FROM_SUBPROCESS] = inchannel; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1637,6 +1673,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkin < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[SUBPROCESS_STDIN] = forkin; #else forkin = forkout = -1; #endif /* not USG, or USG_SUBTTY_WORKS */ @@ -1645,23 +1682,17 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) } else { - if (emacs_pipe (sv) != 0) + if (emacs_pipe (p->open_fd + SUBPROCESS_STDIN) != 0 + || emacs_pipe (p->open_fd + READ_FROM_SUBPROCESS) != 0) report_file_error ("Creating pipe", Qnil); - inchannel = sv[0]; - forkout = sv[1]; - if (emacs_pipe (sv) != 0) - { - int pipe_errno = errno; - emacs_close (inchannel); - emacs_close (forkout); - report_file_errno ("Creating pipe", Qnil, pipe_errno); - } - outchannel = sv[1]; - forkin = sv[0]; + forkin = p->open_fd[SUBPROCESS_STDIN]; + outchannel = p->open_fd[WRITE_TO_SUBPROCESS]; + inchannel = p->open_fd[READ_FROM_SUBPROCESS]; + forkout = p->open_fd[SUBPROCESS_STDOUT]; } #ifndef WINDOWSNT - if (emacs_pipe (wait_child_setup) != 0) + if (emacs_pipe (p->open_fd + READ_FROM_EXEC_MONITOR) != 0) report_file_error ("Creating pipe", Qnil); #endif @@ -1670,16 +1701,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Record this as an active process, with its channels. */ chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + p->infd = inchannel; + p->outfd = outchannel; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = pty_flag; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = pty_flag; + pset_status (p, Qrun); FD_SET (inchannel, &input_wait_mask); FD_SET (inchannel, &non_keyboard_wait_mask); @@ -1699,25 +1730,21 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) { Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; - Lisp_Object volatile process_volatile = process; char **volatile new_argv_volatile = new_argv; int volatile forkin_volatile = forkin; int volatile forkout_volatile = forkout; - int volatile wait_child_setup_0_volatile = wait_child_setup[0]; - int volatile wait_child_setup_1_volatile = wait_child_setup[1]; + struct Lisp_Process *p_volatile = p; pid = vfork (); encoded_current_dir = encoded_current_dir_volatile; lisp_pty_name = lisp_pty_name_volatile; - process = process_volatile; new_argv = new_argv_volatile; forkin = forkin_volatile; forkout = forkout_volatile; - wait_child_setup[0] = wait_child_setup_0_volatile; - wait_child_setup[1] = wait_child_setup_1_volatile; + p = p_volatile; - pty_flag = XPROCESS (process)->pty_flag; + pty_flag = p->pty_flag; } if (pid == 0) @@ -1833,42 +1860,42 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* Back in the parent process. */ vfork_errno = errno; - XPROCESS (process)->pid = pid; + p->pid = pid; if (pid >= 0) - XPROCESS (process)->alive = 1; + p->alive = 1; /* Stop blocking in the parent. */ unblock_child_signal (); unblock_input (); - if (forkin >= 0) - emacs_close (forkin); - if (forkin != forkout && forkout >= 0) - emacs_close (forkout); - if (pid < 0) report_file_errno ("Doing vfork", Qnil, vfork_errno); else { /* vfork succeeded. */ + /* Close the pipe ends that the child uses, or the child's pty. */ + close_process_fd (&p->open_fd[SUBPROCESS_STDIN]); + close_process_fd (&p->open_fd[SUBPROCESS_STDOUT]); + #ifdef WINDOWSNT register_child (pid, inchannel); #endif /* WINDOWSNT */ - pset_tty_name (XPROCESS (process), lisp_pty_name); + pset_tty_name (p, lisp_pty_name); #ifndef WINDOWSNT /* Wait for child_setup to complete in case that vfork is - actually defined as fork. The descriptor wait_child_setup[1] + actually defined as fork. The descriptor + XPROCESS (proc)->open_fd[EXEC_MOINTOR_OUTPUT] of a pipe is closed at the child side either by close-on-exec on successful execve or the _exit call in child_setup. */ { char dummy; - emacs_close (wait_child_setup[1]); - emacs_read (wait_child_setup[0], &dummy, 1); - emacs_close (wait_child_setup[0]); + close_process_fd (&p->open_fd[EXEC_MONITOR_OUTPUT]); + emacs_read (p->open_fd[READ_FROM_EXEC_MONITOR], &dummy, 1); + close_process_fd (&p->open_fd[READ_FROM_EXEC_MONITOR]); } #endif } @@ -1877,16 +1904,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) static void create_pty (Lisp_Object process) { + struct Lisp_Process *p = XPROCESS (process); char pty_name[PTY_NAME_SIZE]; - int inchannel, outchannel; + int pty_fd = NILP (Vprocess_connection_type) ? -1 : allocate_pty (pty_name); - inchannel = outchannel = -1; - - if (!NILP (Vprocess_connection_type)) - outchannel = inchannel = allocate_pty (pty_name); - - if (inchannel >= 0) + if (pty_fd >= 0) { + p->open_fd[SUBPROCESS_STDIN] = pty_fd; #if ! defined (USG) || defined (USG_SUBTTY_WORKS) /* On most USG systems it does not work to open the pty's tty here, then close it and reopen it in the child. */ @@ -1895,6 +1919,7 @@ create_pty (Lisp_Object process) int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0); if (forkout < 0) report_file_error ("Opening pty", Qnil); + p->open_fd[WRITE_TO_SUBPROCESS] = forkout; #if defined (DONT_REOPEN_PTY) /* In the case that vfork is defined as fork, the parent process (Emacs) may send some data before the child process completes @@ -1903,33 +1928,32 @@ create_pty (Lisp_Object process) #endif /* DONT_REOPEN_PTY */ #endif /* not USG, or USG_SUBTTY_WORKS */ - fcntl (inchannel, F_SETFL, O_NONBLOCK); - fcntl (outchannel, F_SETFL, O_NONBLOCK); + fcntl (pty_fd, F_SETFL, O_NONBLOCK); /* Record this as an active process, with its channels. As a result, child_setup will close Emacs's side of the pipes. */ - chan_process[inchannel] = process; - XPROCESS (process)->infd = inchannel; - XPROCESS (process)->outfd = outchannel; + chan_process[pty_fd] = process; + p->infd = pty_fd; + p->outfd = pty_fd; /* Previously we recorded the tty descriptor used in the subprocess. It was only used for getting the foreground tty process, so now we just reopen the device (see emacs_get_tty_pgrp) as this is more portable (see USG_SUBTTY_WORKS above). */ - XPROCESS (process)->pty_flag = 1; - pset_status (XPROCESS (process), Qrun); + p->pty_flag = 1; + pset_status (p, Qrun); setup_process_coding_systems (process); - FD_SET (inchannel, &input_wait_mask); - FD_SET (inchannel, &non_keyboard_wait_mask); - if (inchannel > max_process_desc) - max_process_desc = inchannel; + FD_SET (pty_fd, &input_wait_mask); + FD_SET (pty_fd, &non_keyboard_wait_mask); + if (pty_fd > max_process_desc) + max_process_desc = pty_fd; - pset_tty_name (XPROCESS (process), build_string (pty_name)); + pset_tty_name (p, build_string (pty_name)); } - XPROCESS (process)->pid = -2; + p->pid = -2; } @@ -2535,6 +2559,7 @@ usage: (make-serial-process &rest ARGS) */) p = XPROCESS (proc); fd = serial_open (port); + p->open_fd[SUBPROCESS_STDIN] = fd; p->infd = fd; p->outfd = fd; if (fd > max_process_desc) @@ -3297,12 +3322,6 @@ usage: (make-network-process &rest ARGS) */) } #endif - /* Discard the unwind protect for closing S, if any. */ - specpdl_ptr = specpdl + count1; - - /* Unwind bind_polling_period and request_sigio. */ - unbind_to (count, Qnil); - if (s < 0) { /* If non-blocking got this far - and failed - assume non-blocking is @@ -3344,8 +3363,17 @@ usage: (make-network-process &rest ARGS) */) if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) pset_command (p, Qt); p->pid = 0; + + p->open_fd[SUBPROCESS_STDIN] = inch; p->infd = inch; p->outfd = outch; + + /* Discard the unwind protect for closing S, if any. */ + specpdl_ptr = specpdl + count1; + + /* Unwind bind_polling_period and request_sigio. */ + unbind_to (count, Qnil); + if (is_server && socktype != SOCK_DGRAM) pset_status (p, Qlisten); @@ -3784,17 +3812,15 @@ FLAGS is the current flags of the interface. */) static void deactivate_process (Lisp_Object proc) { - register int inchannel, outchannel; - register struct Lisp_Process *p = XPROCESS (proc); + int inchannel; + struct Lisp_Process *p = XPROCESS (proc); + int i; #ifdef HAVE_GNUTLS /* Delete GnuTLS structures in PROC, if any. */ emacs_gnutls_deinit (proc); #endif /* HAVE_GNUTLS */ - inchannel = p->infd; - outchannel = p->outfd; - #ifdef ADAPTIVE_READ_BUFFERING if (p->read_output_delay > 0) { @@ -3805,16 +3831,17 @@ deactivate_process (Lisp_Object proc) } #endif + inchannel = p->infd; + + /* Beware SIGCHLD hereabouts. */ + if (inchannel >= 0) + flush_pending_output (inchannel); + + for (i = 0; i < PROCESS_OPEN_FDS; i++) + close_process_fd (&p->open_fd[i]); + if (inchannel >= 0) { - /* Beware SIGCHLD hereabouts. */ - flush_pending_output (inchannel); - emacs_close (inchannel); - if (outchannel >= 0 && outchannel != inchannel) - emacs_close (outchannel); - - p->infd = -1; - p->outfd = -1; #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (inchannel)) { @@ -4095,6 +4122,7 @@ server_accept_connection (Lisp_Object server, int channel) /* Discard the unwind protect for closing S. */ specpdl_ptr = specpdl + count; + p->open_fd[SUBPROCESS_STDIN] = s; p->infd = s; p->outfd = s; pset_status (p, Qrun); @@ -6014,7 +6042,8 @@ process has been transmitted to the serial port. */) } else { - int old_outfd, new_outfd; + int old_outfd = XPROCESS (proc)->outfd; + int new_outfd; #ifdef HAVE_SHUTDOWN /* If this is a network connection, or socketpair is used @@ -6022,18 +6051,15 @@ process has been transmitted to the serial port. */) (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ if (EQ (XPROCESS (proc)->type, Qnetwork) - || XPROCESS (proc)->outfd == XPROCESS (proc)->infd) - shutdown (XPROCESS (proc)->outfd, 1); - /* In case of socketpair, outfd == infd, so don't close it. */ - if (XPROCESS (proc)->outfd != XPROCESS (proc)->infd) - emacs_close (XPROCESS (proc)->outfd); -#else /* not HAVE_SHUTDOWN */ - emacs_close (XPROCESS (proc)->outfd); -#endif /* not HAVE_SHUTDOWN */ + || XPROCESS (proc)->infd == old_outfd) + shutdown (old_outfd, 1); +#endif + close_process_fd (&XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS]); new_outfd = emacs_open (NULL_DEVICE, O_WRONLY, 0); if (new_outfd < 0) - emacs_abort (); - old_outfd = XPROCESS (proc)->outfd; + report_file_error ("Opening null device", Qnil); + XPROCESS (proc)->open_fd[WRITE_TO_SUBPROCESS] = new_outfd; + XPROCESS (proc)->outfd = new_outfd; if (!proc_encode_coding_system[new_outfd]) proc_encode_coding_system[new_outfd] @@ -6042,8 +6068,6 @@ process has been transmitted to the serial port. */) = *proc_encode_coding_system[old_outfd]; memset (proc_encode_coding_system[old_outfd], 0, sizeof (struct coding_system)); - - XPROCESS (proc)->outfd = new_outfd; } return process; } @@ -6120,7 +6144,8 @@ handle_child_signal (int sig) bool all_pids_are_fixnums = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); - Lisp_Object xpid = XCAR (tail); + Lisp_Object head = XCAR (tail); + Lisp_Object xpid = XCAR (head); if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) { pid_t deleted_pid; @@ -6129,7 +6154,11 @@ handle_child_signal (int sig) else deleted_pid = XFLOAT_DATA (xpid); if (child_status_changed (deleted_pid, 0, 0)) - XSETCAR (tail, Qnil); + { + if (STRINGP (XCDR (head))) + unlink (SSDATA (XCDR (head))); + XSETCAR (tail, Qnil); + } } } -- cgit v1.2.1 From 297a545bb4482efe73456afa4a7d5aae67fd0fdb Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 12 Aug 2013 13:17:32 -0700 Subject: * process.c (deactivate_process): Reset fds to -1. This fixes a problem introduced by the Bug#15035 patch when using GPG. Reported by Herbert J. Skuhra. --- src/process.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index a2bcffe5160..c803d69d6d8 100644 --- a/src/process.c +++ b/src/process.c @@ -3842,6 +3842,8 @@ deactivate_process (Lisp_Object proc) if (inchannel >= 0) { + p->infd = -1; + p->outfd = -1; #ifdef DATAGRAM_SOCKETS if (DATAGRAM_CHAN_P (inchannel)) { -- cgit v1.2.1 From d5a1acfaa5671f09cbb8da211a5283394d8b907f Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 15 Aug 2013 18:52:53 +0400 Subject: * lisp.h (FOR_EACH_ALIST_VALUE): New macro to do `for' loops over alist values. * buffer.h (FOR_EACH_BUFFER): * process.c (FOR_EACH_PROCESS): Use it. (handle_child_signal, status_notify, Fget_buffer_process) (kill_buffer_processes): Use FOR_EACH_PROCESS. --- src/process.c | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index c803d69d6d8..892a5aa86c5 100644 --- a/src/process.c +++ b/src/process.c @@ -361,6 +361,12 @@ static struct sockaddr_and_len { #define DATAGRAM_CONN_P(proc) (0) #endif +/* FOR_EACH_PROCESS (LIST_VAR, PROC_VAR) followed by a statement is + a `for' loop which iterates over processes from Vprocess_alist. */ + +#define FOR_EACH_PROCESS(list_var, proc_var) \ + FOR_EACH_ALIST_VALUE (Vprocess_alist, list_var, proc_var) + /* These setters are used only in this file, so they can be private. */ static void pset_buffer (struct Lisp_Process *p, Lisp_Object val) @@ -6135,7 +6141,7 @@ static signal_handler_t volatile lib_child_handler; static void handle_child_signal (int sig) { - Lisp_Object tail; + Lisp_Object tail, proc; /* Find the process that signaled us, and record its status. */ @@ -6165,9 +6171,8 @@ handle_child_signal (int sig) } /* Otherwise, if it is asynchronous, it is in Vprocess_alist. */ - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) + FOR_EACH_PROCESS (tail, proc) { - Lisp_Object proc = XCDR (XCAR (tail)); struct Lisp_Process *p = XPROCESS (proc); int status; @@ -6322,13 +6327,10 @@ status_notify (struct Lisp_Process *deleting_process) that we run, we get called again to handle their status changes. */ update_tick = process_tick; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) + FOR_EACH_PROCESS (tail, proc) { Lisp_Object symbol; - register struct Lisp_Process *p; - - proc = Fcdr (XCAR (tail)); - p = XPROCESS (proc); + register struct Lisp_Process *p = XPROCESS (proc); if (p->tick != p->update_tick) { @@ -6851,12 +6853,9 @@ BUFFER may be a buffer or the name of one. */) buf = Fget_buffer (buffer); if (NILP (buf)) return Qnil; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) - { - proc = Fcdr (XCAR (tail)); - if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf)) - return proc; - } + FOR_EACH_PROCESS (tail, proc) + if (EQ (XPROCESS (proc)->buffer, buf)) + return proc; #endif /* subprocesses */ return Qnil; } @@ -6889,18 +6888,14 @@ kill_buffer_processes (Lisp_Object buffer) #ifdef subprocesses Lisp_Object tail, proc; - for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail)) - { - proc = XCDR (XCAR (tail)); - if (PROCESSP (proc) - && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer))) - { - if (NETCONN_P (proc) || SERIALCONN_P (proc)) - Fdelete_process (proc); - else if (XPROCESS (proc)->infd >= 0) - process_send_signal (proc, SIGHUP, Qnil, 1); - } - } + FOR_EACH_PROCESS (tail, proc) + if (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)) + { + if (NETCONN_P (proc) || SERIALCONN_P (proc)) + Fdelete_process (proc); + else if (XPROCESS (proc)->infd >= 0) + process_send_signal (proc, SIGHUP, Qnil, 1); + } #else /* subprocesses */ /* Since we have no subprocesses, this does nothing. */ #endif /* subprocesses */ -- cgit v1.2.1 From 526e5233cc0e2375798bdc79329a893302fdfb4b Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 15 Aug 2013 22:15:51 -0700 Subject: Spelling fixes. --- src/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 892a5aa86c5..64cb401c06a 100644 --- a/src/process.c +++ b/src/process.c @@ -1893,7 +1893,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) #ifndef WINDOWSNT /* Wait for child_setup to complete in case that vfork is actually defined as fork. The descriptor - XPROCESS (proc)->open_fd[EXEC_MOINTOR_OUTPUT] + XPROCESS (proc)->open_fd[EXEC_MONITOR_OUTPUT] of a pipe is closed at the child side either by close-on-exec on successful execve or the _exit call in child_setup. */ { -- cgit v1.2.1 From 2249012558e589b9382e068326116dbd909bbb81 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 18 Aug 2013 22:46:17 -0700 Subject: * process.c (handle_child_signal): Fix crash; deleted pid. This was introduced by my 2013-08-12 fix for Bug#15035. Fixes: debbugs:15106 --- src/process.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 64cb401c06a..c4dd87a6b48 100644 --- a/src/process.c +++ b/src/process.c @@ -6153,7 +6153,10 @@ handle_child_signal (int sig) = (MOST_NEGATIVE_FIXNUM <= TYPE_MINIMUM (pid_t) && TYPE_MAXIMUM (pid_t) <= MOST_POSITIVE_FIXNUM); Lisp_Object head = XCAR (tail); - Lisp_Object xpid = XCAR (head); + Lisp_Object xpid; + if (! CONSP (head)) + continue; + xpid = XCAR (head); if (all_pids_are_fixnums ? INTEGERP (xpid) : NUMBERP (xpid)) { pid_t deleted_pid; -- cgit v1.2.1 From 0d7c1e66ffad14f76fbd226d50113a61c738806c Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 20 Aug 2013 22:39:51 -0700 Subject: * process.c (allocate_pty) [PTY_OPEN]: Set fd's FD_CLOEXEC flag. We can't portably rely on PTY_OPEN doing that, even if it calls posix_openpt with O_CLOEXEC. --- src/process.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index c4dd87a6b48..349ec26534b 100644 --- a/src/process.c +++ b/src/process.c @@ -687,6 +687,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) if (fd >= 0) { +#ifdef PTY_OPEN + /* Set FD's close-on-exec flag. This is needed even if + PT_OPEN calls posix_openpt with O_CLOEXEC, since POSIX + doesn't require support for that combination. + Multithreaded platforms where posix_openpt ignores + O_CLOEXEC (or where PTY_OPEN doesn't call posix_openpt) + have a race condition between the PTY_OPEN and here. */ + fcntl (fd, F_SETFD, FD_CLOEXEC); +#endif /* check to make certain that both sides are available this avoids a nasty yet stupid bug in rlogins */ #ifdef PTY_TTY_NAME_SPRINTF -- cgit v1.2.1 From 2649579468273544ead2ed1c16b224a75ec3a895 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 22 Aug 2013 11:29:51 -0700 Subject: * process.c (flush_pending_output): Remove stub. All uses removed. --- src/process.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 349ec26534b..75cb590fc57 100644 --- a/src/process.c +++ b/src/process.c @@ -3846,15 +3846,12 @@ deactivate_process (Lisp_Object proc) } #endif - inchannel = p->infd; - /* Beware SIGCHLD hereabouts. */ - if (inchannel >= 0) - flush_pending_output (inchannel); for (i = 0; i < PROCESS_OPEN_FDS; i++) close_process_fd (&p->open_fd[i]); + inchannel = p->infd; if (inchannel >= 0) { p->infd = -1; @@ -5785,10 +5782,9 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, return; } - switch (signo) - { #ifdef SIGCONT - case SIGCONT: + if (signo == SIGCONT) + { p->raw_status_new = 0; pset_status (p, Qrun); p->tick = ++process_tick; @@ -5797,14 +5793,8 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, status_notify (NULL); redisplay_preserve_echo_area (13); } - break; -#endif /* ! defined (SIGCONT) */ - case SIGINT: - case SIGQUIT: - case SIGKILL: - flush_pending_output (p->infd); - break; } +#endif /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any -- cgit v1.2.1 From c365c3558065fca4c11c3f46605d1045763485ab Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Aug 2013 10:57:07 -0700 Subject: Don't let very long directory names overrun the stack. Fix some related minor problems involving "//", vfork. * callproc.c (encode_current_directory): New function. (call_process): Don't append "/"; not needed. * fileio.c (file_name_as_directory_slop): New constant. (file_name_as_directory): Allow SRC to be longer than SRCLEN; this can save the caller having to alloca. (Ffile_name_as_directory, Fdirectory_file_name, Fexpand_file_name): Use SAFE_ALLOCA, not alloca. (directory_file_name, Fexpand_file_name): Leave leading "//" alone, since it can be special even on POSIX platforms. * callproc.c (call_process): * process.c (Fformat_network_address): * sysdep.c (sys_subshell): Use encode_current_directory rather than rolling our own. (create_process): No need to encode directory; caller does that now. * process.h (encode_current_directory): New decl. * sysdep.c (sys_subshell): Work even if vfork trashes saved_handlers. Rework to avoid 'goto xyzzy;'. --- src/process.c | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 75cb590fc57..ea1129ffbb8 100644 --- a/src/process.c +++ b/src/process.c @@ -1408,22 +1408,9 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) function. The argument list is protected by the caller, so all we really have to worry about is buffer. */ { - struct gcpro gcpro1, gcpro2; - - current_dir = BVAR (current_buffer, directory); - - GCPRO2 (buffer, current_dir); - - current_dir = Funhandled_file_name_directory (current_dir); - if (NILP (current_dir)) - /* If the file name handler says that current_dir is unreachable, use - a sensible default. */ - current_dir = build_string ("~/"); - current_dir = expand_and_dir_to_file (current_dir, Qnil); - if (NILP (Ffile_accessible_directory_p (current_dir))) - report_file_error ("Setting current directory", - BVAR (current_buffer, directory)); - + struct gcpro gcpro1; + GCPRO1 (buffer); + current_dir = encode_current_directory (); UNGCPRO; } @@ -1670,7 +1657,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; Lisp_Object lisp_pty_name = Qnil; - Lisp_Object encoded_current_dir; inchannel = outchannel = -1; @@ -1735,15 +1721,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) /* This may signal an error. */ setup_process_coding_systems (process); - encoded_current_dir = ENCODE_FILE (current_dir); - block_input (); block_child_signal (); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ { - Lisp_Object volatile encoded_current_dir_volatile = encoded_current_dir; + Lisp_Object volatile current_dir_volatile = current_dir; Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name; char **volatile new_argv_volatile = new_argv; int volatile forkin_volatile = forkin; @@ -1752,7 +1736,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) pid = vfork (); - encoded_current_dir = encoded_current_dir_volatile; + current_dir = current_dir_volatile; lisp_pty_name = lisp_pty_name_volatile; new_argv = new_argv_volatile; forkin = forkin_volatile; @@ -1864,11 +1848,9 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (pty_flag) child_setup_tty (xforkout); #ifdef WINDOWSNT - pid = child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #else /* not WINDOWSNT */ - child_setup (xforkin, xforkout, xforkout, - new_argv, 1, encoded_current_dir); + child_setup (xforkin, xforkout, xforkout, new_argv, 1, current_dir); #endif /* not WINDOWSNT */ } -- cgit v1.2.1 From 9c05bccfb9cd29ab66b5c46643467671315a0f29 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 23 Aug 2013 19:23:34 -0700 Subject: System-dependent integer overflow fixes. * process.c (Fset_process_window_size): Signal an error if the window size is outside the range supported by the lower level. * sysdep.c (set_window_size): Return negative on error, nonnegative on success, rather than -1, 0, 1 on not in system, failure, success. This is simpler. Caller changed. (serial_configure): Remove unnecessary initialization of local. (procfs_get_total_memory) [GNU_LINUX]: Don't assume system memory size fits in unsigned long; this isn't true on some 32-bit hosts. Avoid buffer overrun if some future version of /proc/meminfo has a variable name longer than 20 bytes. (system_process_attributes) [__FreeBSD__]: Don't assume hw.availpages fits in 'int'. --- src/process.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index ea1129ffbb8..c5e691bf602 100644 --- a/src/process.c +++ b/src/process.c @@ -1140,15 +1140,18 @@ See `set-process-sentinel' for more info on sentinels. */) DEFUN ("set-process-window-size", Fset_process_window_size, Sset_process_window_size, 3, 3, 0, doc: /* Tell PROCESS that it has logical window size HEIGHT and WIDTH. */) - (register Lisp_Object process, Lisp_Object height, Lisp_Object width) + (Lisp_Object process, Lisp_Object height, Lisp_Object width) { CHECK_PROCESS (process); - CHECK_RANGED_INTEGER (height, 0, INT_MAX); - CHECK_RANGED_INTEGER (width, 0, INT_MAX); + + /* All known platforms store window sizes as 'unsigned short'. */ + CHECK_RANGED_INTEGER (height, 0, USHRT_MAX); + CHECK_RANGED_INTEGER (width, 0, USHRT_MAX); if (XPROCESS (process)->infd < 0 - || set_window_size (XPROCESS (process)->infd, - XINT (height), XINT (width)) <= 0) + || (set_window_size (XPROCESS (process)->infd, + XINT (height), XINT (width)) + < 0)) return Qnil; else return Qt; -- cgit v1.2.1 From 43aac990c339c0fc3304aa476ebc8ea8467f107e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 27 Aug 2013 11:47:55 -0700 Subject: Simplify EMACS_TIME-related code. This portability layer is no longer needed, since Emacs has been using struct timespec as a portability layer for some time. Merge from gnulib, incorporating: 2013-08-27 timespec: new convenience constants and function * src/atimer.h, src/buffer.h, src/dispextern.h, src/xgselect.h: Include rather than "systime.h"; that's all that's needed now. * src/dispnew.c: Include rather than "systime.h"; that's all that's needed now. * src/systime.h (EMACS_TIME): Remove. All uses changed to struct timespec. (EMACS_TIME_RESOLUTION): Remove. All uses changed to TIMESPEC_RESOLUTION. (LOG10_EMACS_TIME_RESOLUTION): Remove. All uses changed to LOG10_TIMESPEC_RESOLUTION. (EMACS_SECS, emacs_secs_addr): Remove. All uses changed to tv_sec. (EMACS_NSECS): Remove. All uses changed to tv_nsec. (make_emacs_time): Remove. All used changed to make_timespec. (invalid_timespec): Rename from invalid_emacs_time. All uses changed. (current_timespec): Rename from current_emacs_time. All uses changed. (add_emacs_time): Remove. All uses changed to timespec_add. (sub_emacs_time): Remove. All uses change dot timespec_sub. (EMACS_TIME_SIGN): Remove. All uses changed to timespec_sign. (timespec_valid_p): Rename from EMACS_TIME_VALID_P. All uses changed. (EMACS_TIME_FROM_DOUBLE): Remove. All uses changed to dtotimespec. (EMACS_TIME_TO_DOUBLE): Remove. All uses changed to timespectod. (current_timespec): Rename from current_emacs_time. All uses changed. (EMACS_TIME_EQ, EMACS_TIME_LT, EMACS_TIME_LE): Remove. All uses changed to timespec_cmp. * src/xgselect.c: Include , since our .h files don't. --- src/process.c | 64 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index c5e691bf602..3b62f45bf0a 100644 --- a/src/process.c +++ b/src/process.c @@ -133,7 +133,7 @@ along with GNU Emacs. If not, see . */ #ifdef WINDOWSNT extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, - EMACS_TIME *, void *); + struct timespec *, void *); #endif #ifndef SOCK_CLOEXEC @@ -261,7 +261,7 @@ static EMACS_INT update_tick; #endif #ifdef ADAPTIVE_READ_BUFFERING -#define READ_OUTPUT_DELAY_INCREMENT (EMACS_TIME_RESOLUTION / 100) +#define READ_OUTPUT_DELAY_INCREMENT (TIMESPEC_RESOLUTION / 100) #define READ_OUTPUT_DELAY_MAX (READ_OUTPUT_DELAY_INCREMENT * 5) #define READ_OUTPUT_DELAY_MAX_MAX (READ_OUTPUT_DELAY_INCREMENT * 7) @@ -3932,9 +3932,9 @@ Return non-nil if we received any output before the timeout expired. */) { if (XFLOAT_DATA (seconds) > 0) { - EMACS_TIME t = EMACS_TIME_FROM_DOUBLE (XFLOAT_DATA (seconds)); - secs = min (EMACS_SECS (t), WAIT_READING_MAX); - nsecs = EMACS_NSECS (t); + struct timespec t = dtotimespec (XFLOAT_DATA (seconds)); + secs = min (t.tv_sec, WAIT_READING_MAX); + nsecs = t.tv_nsec; } } else @@ -4239,7 +4239,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool no_avail; int xerrno; Lisp_Object proc; - EMACS_TIME timeout, end_time; + struct timespec timeout, end_time; int wait_channel = -1; bool got_some_input = 0; ptrdiff_t count = SPECPDL_INDEX (); @@ -4272,8 +4272,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, compute the absolute time to return at. */ if (time_limit || nsecs > 0) { - timeout = make_emacs_time (time_limit, nsecs); - end_time = add_emacs_time (current_emacs_time (), timeout); + timeout = make_timespec (time_limit, nsecs); + end_time = timespec_add (current_timespec (), timeout); } while (1) @@ -4300,18 +4300,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, gobble output available now but don't wait at all. */ - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); } else if (time_limit || nsecs > 0) { - EMACS_TIME now = current_emacs_time (); - if (EMACS_TIME_LE (end_time, now)) + struct timespec now = current_timespec (); + if (timespec_cmp (end_time, now) <= 0) break; - timeout = sub_emacs_time (end_time, now); + timeout = timespec_sub (end_time, now); } else { - timeout = make_emacs_time (100000, 0); + timeout = make_timespec (100000, 0); } /* Normally we run timers here. @@ -4321,7 +4321,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (NILP (wait_for_cell) && just_wait_proc >= 0) { - EMACS_TIME timer_delay; + struct timespec timer_delay; do { @@ -4356,9 +4356,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* A negative timeout means do not wait at all. */ if (nsecs >= 0) { - if (EMACS_TIME_VALID_P (timer_delay)) + if (timespec_valid_p (timer_delay)) { - if (EMACS_TIME_LT (timer_delay, timeout)) + if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; timeout_reduced_for_timers = 1; @@ -4396,7 +4396,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, Atemp = input_wait_mask; Ctemp = write_mask; - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); if ((pselect (max (max_process_desc, max_input_desc) + 1, &Atemp, #ifdef NON_BLOCKING_CONNECT @@ -4518,8 +4518,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { - int nsecs = EMACS_NSECS (timeout); - if (EMACS_SECS (timeout) > 0 || nsecs > READ_OUTPUT_DELAY_MAX) + int nsecs = timeout.tv_nsec; + if (timeout.tv_sec > 0 || nsecs > READ_OUTPUT_DELAY_MAX) nsecs = READ_OUTPUT_DELAY_MAX; for (channel = 0; check_delay > 0 && channel <= max_process_desc; channel++) { @@ -4539,7 +4539,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, nsecs = XPROCESS (proc)->read_output_delay; } } - timeout = make_emacs_time (0, nsecs); + timeout = make_timespec (0, nsecs); process_output_skip = 0; } #endif @@ -6543,7 +6543,7 @@ keyboard_bit_set (fd_set *mask) /* Defined on msdos.c. */ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, - EMACS_TIME *, void *); + struct timespec *, void *); /* Implementation of wait_reading_process_output, assuming that there are no subprocesses. Used only by the MS-DOS build. @@ -6582,7 +6582,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct Lisp_Process *wait_proc, int just_wait_proc) { register int nfds; - EMACS_TIME end_time, timeout; + struct timespec end_time, timeout; if (time_limit < 0) { @@ -6595,8 +6595,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* What does time_limit really mean? */ if (time_limit || nsecs > 0) { - timeout = make_emacs_time (time_limit, nsecs); - end_time = add_emacs_time (current_emacs_time (), timeout); + timeout = make_timespec (time_limit, nsecs); + end_time = timespec_add (current_timespec (), timeout); } /* Turn off periodic alarms (in case they are in use) @@ -6629,18 +6629,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, gobble output available now but don't wait at all. */ - timeout = make_emacs_time (0, 0); + timeout = make_timespec (0, 0); } else if (time_limit || nsecs > 0) { - EMACS_TIME now = current_emacs_time (); - if (EMACS_TIME_LE (end_time, now)) + struct timespec now = current_timespec (); + if (timespec_cmp (end_time, now) <= 0) break; - timeout = sub_emacs_time (end_time, now); + timeout = timespec_sub (end_time, now); } else { - timeout = make_emacs_time (100000, 0); + timeout = make_timespec (100000, 0); } /* If our caller will not immediately handle keyboard events, @@ -6649,7 +6649,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, call timer_delay on their own.) */ if (NILP (wait_for_cell)) { - EMACS_TIME timer_delay; + struct timespec timer_delay; do { @@ -6669,9 +6669,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && requeued_events_pending_p ()) break; - if (EMACS_TIME_VALID_P (timer_delay) && nsecs >= 0) + if (timespec_valid_p (timer_delay) && nsecs >= 0) { - if (EMACS_TIME_LT (timer_delay, timeout)) + if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; timeout_reduced_for_timers = 1; -- cgit v1.2.1 From d486344e6fd74e4769cc7b3d09a1ea87387c5a11 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 27 Aug 2013 12:36:28 -0700 Subject: Simplify SELECT_TYPE-related code. Like EMACS_TIME, this portability layer is no longer needed, since Emacs has been using fd_set as a portability layer for some time. * sysselect.h (FD_SETSIZE): Rename from MAXDESC. All uses changed. (SELECT_TYPE): Remove. All uses changed to fd_set. (fd_set) [!FD_SET]: New typedef. --- src/process.c | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index 3b62f45bf0a..b52622ec1b6 100644 --- a/src/process.c +++ b/src/process.c @@ -132,7 +132,7 @@ along with GNU Emacs. If not, see . */ #endif #ifdef WINDOWSNT -extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, +extern int sys_select (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *); #endif @@ -280,7 +280,7 @@ static bool process_output_skip; static void create_process (Lisp_Object, char **, Lisp_Object); #ifdef USABLE_SIGIO -static bool keyboard_bit_set (SELECT_TYPE *); +static bool keyboard_bit_set (fd_set *); #endif static void deactivate_process (Lisp_Object); static void status_notify (struct Lisp_Process *); @@ -299,26 +299,26 @@ static void exec_sentinel (Lisp_Object proc, Lisp_Object reason); /* Mask of bits indicating the descriptors that we wait for input on. */ -static SELECT_TYPE input_wait_mask; +static fd_set input_wait_mask; /* Mask that excludes keyboard input descriptor(s). */ -static SELECT_TYPE non_keyboard_wait_mask; +static fd_set non_keyboard_wait_mask; /* Mask that excludes process input descriptor(s). */ -static SELECT_TYPE non_process_wait_mask; +static fd_set non_process_wait_mask; /* Mask for selecting for write. */ -static SELECT_TYPE write_mask; +static fd_set write_mask; #ifdef NON_BLOCKING_CONNECT /* Mask of bits indicating the descriptors that we wait for connect to complete on. Once they complete, they are removed from this mask and added to the input_wait_mask and non_keyboard_wait_mask. */ -static SELECT_TYPE connect_wait_mask; +static fd_set connect_wait_mask; /* Number of bits set in connect_wait_mask. */ static int num_pending_connects; @@ -331,7 +331,7 @@ static int max_process_desc; static int max_input_desc; /* Indexed by descriptor, gives the process (if any) for that descriptor */ -static Lisp_Object chan_process[MAXDESC]; +static Lisp_Object chan_process[FD_SETSIZE]; /* Alist of elements (NAME . PROCESS) */ static Lisp_Object Vprocess_alist; @@ -342,18 +342,18 @@ static Lisp_Object Vprocess_alist; output from the process is to read at least one char. Always -1 on systems that support FIONREAD. */ -static int proc_buffered_char[MAXDESC]; +static int proc_buffered_char[FD_SETSIZE]; /* Table of `struct coding-system' for each process. */ -static struct coding_system *proc_decode_coding_system[MAXDESC]; -static struct coding_system *proc_encode_coding_system[MAXDESC]; +static struct coding_system *proc_decode_coding_system[FD_SETSIZE]; +static struct coding_system *proc_encode_coding_system[FD_SETSIZE]; #ifdef DATAGRAM_SOCKETS /* Table of `partner address' for datagram sockets. */ static struct sockaddr_and_len { struct sockaddr *sa; int len; -} datagram_address[MAXDESC]; +} datagram_address[FD_SETSIZE]; #define DATAGRAM_CHAN_P(chan) (datagram_address[chan].sa != 0) #define DATAGRAM_CONN_P(proc) (PROCESSP (proc) && datagram_address[XPROCESS (proc)->infd].sa != 0) #else @@ -458,7 +458,7 @@ static struct fd_callback_data #define FOR_READ 1 #define FOR_WRITE 2 int condition; /* mask of the defines above. */ -} fd_callback_info[MAXDESC]; +} fd_callback_info[FD_SETSIZE]; /* Add a file descriptor FD to be monitored for when read is possible. @@ -467,7 +467,7 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -480,7 +480,7 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -497,7 +497,7 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -528,7 +528,7 @@ delete_input_desc (int fd) void delete_write_fd (int fd) { - eassert (fd < MAXDESC); + eassert (fd < FD_SETSIZE); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) @@ -3232,7 +3232,7 @@ usage: (make-network-process &rest ARGS) */) wait for completion is pselect(). */ int sc; socklen_t len; - SELECT_TYPE fdset; + fd_set fdset; retry_select: FD_ZERO (&fdset); FD_SET (s, &fdset); @@ -4232,8 +4232,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct Lisp_Process *wait_proc, int just_wait_proc) { int channel, nfds; - SELECT_TYPE Available; - SELECT_TYPE Writeok; + fd_set Available; + fd_set Writeok; bool check_write; int check_delay; bool no_avail; @@ -4387,8 +4387,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, timeout to get our attention. */ if (update_tick != process_tick) { - SELECT_TYPE Atemp; - SELECT_TYPE Ctemp; + fd_set Atemp; + fd_set Ctemp; if (kbd_on_hold_p ()) FD_ZERO (&Atemp); @@ -4571,7 +4571,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, the gnutls library -- 2.12.14 has been confirmed to need it. See http://comments.gmane.org/gmane.emacs.devel/145074 */ - for (channel = 0; channel < MAXDESC; ++channel) + for (channel = 0; channel < FD_SETSIZE; ++channel) if (! NILP (chan_process[channel])) { struct Lisp_Process *p = @@ -6542,7 +6542,7 @@ keyboard_bit_set (fd_set *mask) #else /* not subprocesses */ /* Defined on msdos.c. */ -extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *, +extern int sys_select (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *); /* Implementation of wait_reading_process_output, assuming that there @@ -6608,7 +6608,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { bool timeout_reduced_for_timers = 0; - SELECT_TYPE waitchannels; + fd_set waitchannels; int xerrno; /* If calling from keyboard input, do not quit @@ -7072,7 +7072,7 @@ init_process_emacs (void) Vprocess_alist = Qnil; deleted_pid_list = Qnil; - for (i = 0; i < MAXDESC; i++) + for (i = 0; i < FD_SETSIZE; i++) { chan_process[i] = Qnil; proc_buffered_char[i] = -1; -- cgit v1.2.1 From 032f74518a71a7fe0afd2e7d0eee11bfb7ae90d9 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Thu, 29 Aug 2013 20:36:54 +0400 Subject: * intervals.c (set_point_from_marker): New function. * editfns.c (Fgoto_char): * process.c (Finternal_default_process_filter): * window.c (select_window_1): Use it. * buffer.h (set_point_from_marker): Add prototype. --- src/process.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src/process.c') diff --git a/src/process.c b/src/process.c index b52622ec1b6..20f84990d6f 100644 --- a/src/process.c +++ b/src/process.c @@ -5178,15 +5178,10 @@ DEFUN ("internal-default-process-filter", Finternal_default_process_filter, bset_read_only (current_buffer, Qnil); - /* Insert new output into buffer - at the current end-of-output marker, - thus preserving logical ordering of input and output. */ + /* Insert new output into buffer at the current end-of-output + marker, thus preserving logical ordering of input and output. */ if (XMARKER (p->mark)->buffer) - SET_PT_BOTH (clip_to_bounds (BEGV, - marker_position (p->mark), ZV), - clip_to_bounds (BEGV_BYTE, - marker_byte_position (p->mark), - ZV_BYTE)); + set_point_from_marker (p->mark); else SET_PT_BOTH (ZV, ZV_BYTE); before = PT; -- cgit v1.2.1