summaryrefslogtreecommitdiff
path: root/src/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c233
1 files changed, 95 insertions, 138 deletions
diff --git a/src/process.c b/src/process.c
index dc37bfe7067..33d8ccbbc35 100644
--- a/src/process.c
+++ b/src/process.c
@@ -785,19 +785,16 @@ status_message (struct Lisp_Process *p)
return Fcopy_sequence (Fsymbol_name (symbol));
}
-#ifdef HAVE_PTYS
-
-/* The file name of the pty opened by allocate_pty. */
-static char pty_name[24];
+enum { PTY_NAME_SIZE = 24 };
/* Open an available pty, returning a file descriptor.
- Return -1 on failure.
- The file name of the terminal corresponding to the pty
- is left in the variable pty_name. */
+ Store into PTY_NAME the file name of the terminal corresponding to the pty.
+ Return -1 on failure. */
static int
-allocate_pty (void)
+allocate_pty (char pty_name[PTY_NAME_SIZE])
{
+#ifdef HAVE_PTYS
int fd;
#ifdef PTY_ITERATION
@@ -842,9 +839,9 @@ allocate_pty (void)
return fd;
}
}
+#endif /* HAVE_PTYS */
return -1;
}
-#endif /* HAVE_PTYS */
static Lisp_Object
make_process (Lisp_Object name)
@@ -1008,7 +1005,7 @@ nil, indicating the current buffer's process. */)
p->raw_status_new = 0;
if (NETCONN1_P (p) || SERIALCONN1_P (p))
{
- pset_status (p, Fcons (Qexit, Fcons (make_number (0), Qnil)));
+ pset_status (p, list2 (Qexit, make_number (0)));
p->tick = ++process_tick;
status_notify (p);
redisplay_preserve_echo_area (13);
@@ -1403,11 +1400,11 @@ list of keywords. */)
if ((!NETCONN_P (process) && !SERIALCONN_P (process)) || EQ (key, Qt))
return contact;
if (NILP (key) && NETCONN_P (process))
- return Fcons (Fplist_get (contact, QChost),
- Fcons (Fplist_get (contact, QCservice), Qnil));
+ return list2 (Fplist_get (contact, QChost),
+ Fplist_get (contact, QCservice));
if (NILP (key) && SERIALCONN_P (process))
- return Fcons (Fplist_get (contact, QCport),
- Fcons (Fplist_get (contact, QCspeed), Qnil));
+ return list2 (Fplist_get (contact, QCport),
+ Fplist_get (contact, QCspeed));
return Fplist_get (contact, key);
}
@@ -1530,7 +1527,7 @@ Returns nil if format of ADDRESS is invalid. */)
}
DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
- doc: /* Return a list of all processes. */)
+ doc: /* Return a list of all processes that are Emacs sub-processes. */)
(void)
{
return Fmapcar (Qcdr, Vprocess_alist);
@@ -1538,7 +1535,7 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
/* Starting asynchronous inferior processes. */
-static Lisp_Object start_process_unwind (Lisp_Object proc);
+static void start_process_unwind (Lisp_Object proc);
DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
doc: /* Start a program in a subprocess. Return the process object for it.
@@ -1594,7 +1591,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
current_dir = expand_and_dir_to_file (current_dir, Qnil);
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
- Fcons (BVAR (current_buffer, directory), Qnil));
+ BVAR (current_buffer, directory));
UNGCPRO;
}
@@ -1716,7 +1713,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
UNGCPRO;
if (NILP (tem))
- report_file_error ("Searching for program", Fcons (program, Qnil));
+ report_file_error ("Searching for program", program);
tem = Fexpand_file_name (tem, Qnil);
}
else
@@ -1739,7 +1736,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
/* Encode the file name and put it in NEW_ARGV.
That's where the child will use it to execute the program. */
- tem = Fcons (ENCODE_FILE (tem), Qnil);
+ tem = list1 (ENCODE_FILE (tem));
/* Here we encode arguments by the coding system used for sending
data to the process. We don't support using different coding
@@ -1787,7 +1784,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
PROC doesn't have its pid set, then we know someone has signaled
an error and the process wasn't started successfully, so we should
remove it from the process list. */
-static Lisp_Object
+static void
start_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
@@ -1797,14 +1794,6 @@ start_process_unwind (Lisp_Object proc)
-2 is used for a pty with no process, eg for gdb. */
if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2)
remove_process (proc);
-
- return Qnil;
-}
-
-static void
-create_process_1 (struct atimer *timer)
-{
- /* Nothing to do. */
}
@@ -1820,14 +1809,14 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
#endif
int forkin, forkout;
bool pty_flag = 0;
+ char pty_name[PTY_NAME_SIZE];
Lisp_Object lisp_pty_name = Qnil;
Lisp_Object encoded_current_dir;
inchannel = outchannel = -1;
-#ifdef HAVE_PTYS
if (!NILP (Vprocess_connection_type))
- outchannel = inchannel = allocate_pty ();
+ outchannel = inchannel = allocate_pty (pty_name);
if (inchannel >= 0)
{
@@ -1846,13 +1835,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
lisp_pty_name = build_string (pty_name);
}
else
-#endif /* HAVE_PTYS */
{
- if (pipe2 (sv, O_CLOEXEC) != 0)
+ if (emacs_pipe (sv) != 0)
report_file_error ("Creating pipe", Qnil);
inchannel = sv[0];
forkout = sv[1];
- if (pipe2 (sv, O_CLOEXEC) != 0)
+ if (emacs_pipe (sv) != 0)
{
int pipe_errno = errno;
emacs_close (inchannel);
@@ -1864,7 +1852,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
}
#ifndef WINDOWSNT
- if (pipe2 (wait_child_setup, O_CLOEXEC) != 0)
+ if (emacs_pipe (wait_child_setup) != 0)
report_file_error ("Creating pipe", Qnil);
#endif
@@ -1900,7 +1888,6 @@ 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;
- bool volatile pty_flag_volatile = pty_flag;
char **volatile new_argv_volatile = new_argv;
int volatile forkin_volatile = forkin;
int volatile forkout_volatile = forkout;
@@ -1912,12 +1899,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
encoded_current_dir = encoded_current_dir_volatile;
lisp_pty_name = lisp_pty_name_volatile;
process = process_volatile;
- pty_flag = pty_flag_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;
+
+ pty_flag = XPROCESS (process)->pty_flag;
}
if (pid == 0)
@@ -1987,15 +1975,15 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
if (pty_flag)
{
- /* I wonder if emacs_close (emacs_open (pty_name, ...))
+ /* I wonder if emacs_close (emacs_open (SSDATA (lisp_pty_name), ...))
would work? */
if (xforkin >= 0)
emacs_close (xforkin);
- xforkout = xforkin = emacs_open (pty_name, O_RDWR, 0);
+ xforkout = xforkin = emacs_open (SSDATA (lisp_pty_name), O_RDWR, 0);
if (xforkin < 0)
{
- emacs_perror (pty_name);
+ emacs_perror (SSDATA (lisp_pty_name));
_exit (EXIT_CANCELED);
}
@@ -2025,7 +2013,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
pid = child_setup (xforkin, xforkout, xforkout,
new_argv, 1, encoded_current_dir);
#else /* not WINDOWSNT */
- emacs_close (wait_child_setup[0]);
child_setup (xforkin, xforkout, xforkout,
new_argv, 1, encoded_current_dir);
#endif /* not WINDOWSNT */
@@ -2042,14 +2029,13 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
unblock_child_signal ();
unblock_input ();
+ if (forkin >= 0)
+ emacs_close (forkin);
+ if (forkin != forkout && forkout >= 0)
+ emacs_close (forkout);
+
if (pid < 0)
- {
- if (forkin >= 0)
- emacs_close (forkin);
- if (forkin != forkout && forkout >= 0)
- emacs_close (forkout);
- report_file_errno ("Doing vfork", Qnil, vfork_errno);
- }
+ report_file_errno ("Doing vfork", Qnil, vfork_errno);
else
{
/* vfork succeeded. */
@@ -2058,26 +2044,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
register_child (pid, inchannel);
#endif /* WINDOWSNT */
- /* If the subfork execv fails, and it exits,
- this close hangs. I don't know why.
- So have an interrupt jar it loose. */
- {
- struct atimer *timer;
- EMACS_TIME offset = make_emacs_time (1, 0);
-
- stop_polling ();
- timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0);
-
- if (forkin >= 0)
- emacs_close (forkin);
-
- cancel_atimer (timer);
- start_polling ();
- }
-
- if (forkin != forkout && forkout >= 0)
- emacs_close (forkout);
-
pset_tty_name (XPROCESS (process), lisp_pty_name);
#ifndef WINDOWSNT
@@ -2096,17 +2062,16 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
}
}
-void
+static void
create_pty (Lisp_Object process)
{
+ char pty_name[PTY_NAME_SIZE];
int inchannel, outchannel;
- bool pty_flag = 0;
inchannel = outchannel = -1;
-#ifdef HAVE_PTYS
if (!NILP (Vprocess_connection_type))
- outchannel = inchannel = allocate_pty ();
+ outchannel = inchannel = allocate_pty (pty_name);
if (inchannel >= 0)
{
@@ -2125,37 +2090,29 @@ create_pty (Lisp_Object process)
child_setup_tty (forkout);
#endif /* DONT_REOPEN_PTY */
#endif /* not USG, or USG_SUBTTY_WORKS */
- pty_flag = 1;
- }
-#endif /* HAVE_PTYS */
- fcntl (inchannel, F_SETFL, O_NONBLOCK);
- fcntl (outchannel, F_SETFL, O_NONBLOCK);
+ fcntl (inchannel, F_SETFL, O_NONBLOCK);
+ fcntl (outchannel, 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;
+ /* 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;
- /* 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). */
+ /* 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);
- setup_process_coding_systems (process);
+ XPROCESS (process)->pty_flag = 1;
+ pset_status (XPROCESS (process), Qrun);
+ setup_process_coding_systems (process);
- add_process_read_fd (inchannel);
+ pset_tty_name (XPROCESS (process), build_string (pty_name));
+ }
XPROCESS (process)->pid = -2;
-#ifdef HAVE_PTYS
- if (pty_flag)
- pset_tty_name (XPROCESS (process), build_string (pty_name));
- else
-#endif
- pset_tty_name (XPROCESS (process), Qnil);
}
@@ -2515,8 +2472,12 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
}
if (ret < 0)
- report_file_error ("Cannot set network option",
- Fcons (opt, Fcons (val, Qnil)));
+ {
+ int setsockopt_errno = errno;
+ report_file_errno ("Cannot set network option", list2 (opt, val),
+ setsockopt_errno);
+ }
+
return (1 << sopt->optbit);
}
@@ -2648,16 +2609,6 @@ usage: (serial-process-configure &rest ARGS) */)
return Qnil;
}
-/* Used by make-serial-process to recover from errors. */
-static Lisp_Object
-make_serial_process_unwind (Lisp_Object proc)
-{
- if (!PROCESSP (proc))
- emacs_abort ();
- remove_process (proc);
- return Qnil;
-}
-
DEFUN ("make-serial-process", Fmake_serial_process, Smake_serial_process,
0, MANY, 0,
doc: /* Create and return a serial port process.
@@ -2763,10 +2714,10 @@ usage: (make-serial-process &rest ARGS) */)
CHECK_STRING (name);
proc = make_process (name);
specpdl_count = SPECPDL_INDEX ();
- record_unwind_protect (make_serial_process_unwind, proc);
+ record_unwind_protect (remove_process, proc);
p = XPROCESS (proc);
- fd = serial_open (SSDATA (port));
+ fd = serial_open (port);
p->infd = fd;
p->outfd = fd;
if (fd > max_desc)
@@ -2789,7 +2740,7 @@ usage: (make-serial-process &rest ARGS) */)
p->kill_without_query = 1;
if (tem = Fplist_get (contact, QCstop), !NILP (tem))
pset_command (p, Qt);
- p->pty_flag = 0;
+ eassert (! p->pty_flag);
if (!EQ (p->command, Qt))
add_non_keyboard_read_fd (fd);
@@ -3196,7 +3147,7 @@ usage: (make-network-process &rest ARGS) */)
#ifdef POLL_FOR_INPUT
if (socktype != SOCK_DGRAM)
{
- record_unwind_protect (unwind_stop_other_atimers, Qnil);
+ record_unwind_protect_void (run_all_atimers);
bind_polling_period (10);
}
#endif
@@ -3356,7 +3307,7 @@ usage: (make-network-process &rest ARGS) */)
#endif
/* Make us close S if quit. */
- record_unwind_protect (close_file_unwind, make_number (s));
+ record_unwind_protect_int (close_file_unwind, s);
/* Parse network options in the arg list.
We simply ignore anything which isn't a known option (including other keywords).
@@ -3447,16 +3398,16 @@ usage: (make-network-process &rest ARGS) */)
if (errno == EINTR)
goto retry_select;
else
- report_file_error ("select failed", Qnil);
+ report_file_error ("Failed select", Qnil);
}
eassert (sc > 0);
len = sizeof xerrno;
eassert (FD_ISSET (s, &fdset));
if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0)
- report_file_error ("getsockopt failed", Qnil);
+ report_file_error ("Failed getsockopt", Qnil);
if (xerrno)
- report_file_errno ("error during connect", Qnil, xerrno);
+ report_file_errno ("Failed connect", Qnil, xerrno);
break;
}
#endif /* !WINDOWSNT */
@@ -3716,10 +3667,13 @@ format; see the description of ADDRESS in `make-network-process'. */)
ptrdiff_t buf_size = 512;
int s;
Lisp_Object res;
+ ptrdiff_t count;
s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (s < 0)
return Qnil;
+ count = SPECPDL_INDEX ();
+ record_unwind_protect_int (close_file_unwind, s);
do
{
@@ -3735,9 +3689,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
}
while (ifconf.ifc_len == buf_size);
- emacs_close (s);
-
- res = Qnil;
+ res = unbind_to (count, Qnil);
ifreq = ifconf.ifc_req;
while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
{
@@ -3862,6 +3814,7 @@ FLAGS is the current flags of the interface. */)
Lisp_Object elt;
int s;
bool any = 0;
+ ptrdiff_t count;
#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
&& defined HAVE_GETIFADDRS && defined LLADDR)
struct ifaddrs *ifap;
@@ -3876,6 +3829,8 @@ FLAGS is the current flags of the interface. */)
s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (s < 0)
return Qnil;
+ count = SPECPDL_INDEX ();
+ record_unwind_protect_int (close_file_unwind, s);
elt = Qnil;
#if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS)
@@ -3992,9 +3947,7 @@ FLAGS is the current flags of the interface. */)
#endif
res = Fcons (elt, res);
- emacs_close (s);
-
- return any ? res : Qnil;
+ return unbind_to (count, any ? res : Qnil);
}
#endif
#endif /* defined (HAVE_NET_IF_H) */
@@ -4164,6 +4117,7 @@ server_accept_connection (Lisp_Object server, int channel)
#endif
} saddr;
socklen_t len = sizeof saddr;
+ ptrdiff_t count;
s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
@@ -4186,6 +4140,9 @@ server_accept_connection (Lisp_Object server, int channel)
return;
}
+ count = SPECPDL_INDEX ();
+ record_unwind_protect_int (close_file_unwind, s);
+
connect_counter++;
/* Setup a new process to handle the connection. */
@@ -4302,6 +4259,10 @@ server_accept_connection (Lisp_Object server, int channel)
pset_filter (p, ps->filter);
pset_command (p, Qnil);
p->pid = 0;
+
+ /* Discard the unwind protect for closing S. */
+ specpdl_ptr = specpdl + count;
+
p->infd = s;
p->outfd = s;
pset_status (p, Qrun);
@@ -4338,12 +4299,11 @@ server_accept_connection (Lisp_Object server, int channel)
build_string ("\n")));
}
-static Lisp_Object
-wait_reading_process_output_unwind (Lisp_Object data)
+static void
+wait_reading_process_output_unwind (int data)
{
clear_waiting_thread_info ();
- waiting_for_user_input_p = XINT (data);
- return Qnil;
+ waiting_for_user_input_p = data;
}
/* This is here so breakpoints can be put on it. */
@@ -4425,8 +4385,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (wait_proc != NULL)
wait_channel = wait_proc->infd;
- record_unwind_protect (wait_reading_process_output_unwind,
- make_number (waiting_for_user_input_p));
+ record_unwind_protect_int (wait_reading_process_output_unwind,
+ waiting_for_user_input_p);
waiting_for_user_input_p = read_kbd;
if (time_limit < 0)
@@ -4791,7 +4751,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
else if (xerrno == EBADF)
emacs_abort ();
else
- error ("select error: %s", emacs_strerror (xerrno));
+ report_file_errno ("Failed select", Qnil, xerrno);
}
if (no_avail)
@@ -5284,9 +5244,7 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars,
sometimes it's simply wrong to wrap (e.g. when called from
accept-process-output). */
internal_condition_case_1 (read_process_output_call,
- Fcons (outstream,
- Fcons (make_lisp_proc (p),
- Fcons (text, Qnil))),
+ list3 (outstream, make_lisp_proc (p), text),
!NILP (Vdebug_on_error) ? Qnil : Qerror,
read_process_output_error_handler);
@@ -5456,7 +5414,7 @@ write_queue_push (struct Lisp_Process *p, Lisp_Object input_obj,
if (front)
pset_write_queue (p, Fcons (entry, p->write_queue));
else
- pset_write_queue (p, nconc2 (p->write_queue, Fcons (entry, Qnil)));
+ pset_write_queue (p, nconc2 (p->write_queue, list1 (entry)));
}
/* Remove the first element in the write_queue of process P, put its
@@ -5629,7 +5587,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
if (rv >= 0)
written = rv;
else if (errno == EMSGSIZE)
- report_file_error ("sending datagram", Fcons (proc, Qnil));
+ report_file_error ("Sending datagram", proc);
}
else
#endif
@@ -5706,7 +5664,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
}
else
/* This is a real error. */
- report_file_error ("writing to process", Fcons (proc, Qnil));
+ report_file_error ("Writing to process", proc);
}
cur_buf += written;
cur_len -= written;
@@ -6196,7 +6154,7 @@ process has been transmitted to the serial port. */)
{
#ifndef WINDOWSNT
if (tcdrain (XPROCESS (proc)->outfd) != 0)
- error ("tcdrain() failed: %s", emacs_strerror (errno));
+ report_file_error ("Failed tcdrain", Qnil);
#endif /* not WINDOWSNT */
/* Do nothing on Windows because writes are blocking. */
}
@@ -6425,8 +6383,7 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason)
running_asynch_code = 1;
internal_condition_case_1 (read_process_output_call,
- Fcons (sentinel,
- Fcons (proc, Fcons (reason, Qnil))),
+ list3 (sentinel, proc, reason),
!NILP (Vdebug_on_error) ? Qnil : Qerror,
exec_sentinel_error_handler);
@@ -6890,7 +6847,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (xerrno == EINTR)
FD_ZERO (&waitchannels);
else
- error ("select error: %s", emacs_strerror (xerrno));
+ report_file_errno ("Failed select", Qnil, xerrno);
}
/* Check for keyboard input */