summaryrefslogtreecommitdiff
path: root/src/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c157
1 files changed, 61 insertions, 96 deletions
diff --git a/src/process.c b/src/process.c
index 2e2610ffde4..dc37bfe7067 100644
--- a/src/process.c
+++ b/src/process.c
@@ -135,6 +135,37 @@ extern int sys_select (int, SELECT_TYPE *, SELECT_TYPE *, SELECT_TYPE *,
EMACS_TIME *, void *);
#endif
+#ifndef SOCK_CLOEXEC
+# define SOCK_CLOEXEC 0
+#endif
+
+#ifndef HAVE_ACCEPT4
+
+/* Emulate GNU/Linux accept4 and socket well enough for this module. */
+
+static int
+close_on_exec (int fd)
+{
+ if (0 <= fd)
+ fcntl (fd, F_SETFD, FD_CLOEXEC);
+ return fd;
+}
+
+static int
+accept4 (int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+{
+ return close_on_exec (accept (sockfd, addr, addrlen));
+}
+
+static int
+process_socket (int domain, int type, int protocol)
+{
+ return close_on_exec (socket (domain, type, protocol));
+}
+# undef socket
+# define socket(domain, type, protocol) process_socket (domain, type, protocol)
+#endif
+
/* Work around GCC 4.7.0 bug with strict overflow checking; see
<http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>.
These lines can be removed once the GCC bug is fixed. */
@@ -1782,6 +1813,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
{
int inchannel, outchannel;
pid_t pid;
+ int vfork_errno;
int sv[2];
#ifndef WINDOWSNT
int wait_child_setup[2];
@@ -1816,47 +1848,30 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
else
#endif /* HAVE_PTYS */
{
- int tem;
- tem = pipe (sv);
- if (tem < 0)
+ if (pipe2 (sv, O_CLOEXEC) != 0)
report_file_error ("Creating pipe", Qnil);
inchannel = sv[0];
forkout = sv[1];
- tem = pipe (sv);
- if (tem < 0)
+ if (pipe2 (sv, O_CLOEXEC) != 0)
{
+ int pipe_errno = errno;
emacs_close (inchannel);
emacs_close (forkout);
- report_file_error ("Creating pipe", Qnil);
+ report_file_errno ("Creating pipe", Qnil, pipe_errno);
}
outchannel = sv[1];
forkin = sv[0];
}
#ifndef WINDOWSNT
- {
- int tem;
-
- tem = pipe (wait_child_setup);
- if (tem < 0)
- report_file_error ("Creating pipe", Qnil);
- tem = fcntl (wait_child_setup[1], F_GETFD, 0);
- if (tem >= 0)
- tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC);
- if (tem < 0)
- {
- emacs_close (wait_child_setup[0]);
- emacs_close (wait_child_setup[1]);
- report_file_error ("Setting file descriptor flags", Qnil);
- }
- }
+ if (pipe2 (wait_child_setup, O_CLOEXEC) != 0)
+ report_file_error ("Creating pipe", Qnil);
#endif
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. */
+ /* Record this as an active process, with its channels. */
chan_process[inchannel] = process;
XPROCESS (process)->infd = inchannel;
XPROCESS (process)->outfd = outchannel;
@@ -1933,7 +1948,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
tcgetattr (xforkin, &t);
t.c_lflag = LDISC1;
if (tcsetattr (xforkin, TCSANOW, &t) < 0)
- emacs_write (1, "create_process/tcsetattr LDISC1 failed\n", 39);
+ emacs_perror ("create_process/tcsetattr LDISC1");
}
#else
#if defined (NTTYDISC) && defined (TIOCSETD)
@@ -1980,10 +1995,8 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
if (xforkin < 0)
{
- emacs_write (1, "Couldn't open the pty terminal ", 31);
- emacs_write (1, pty_name, strlen (pty_name));
- emacs_write (1, "\n", 1);
- _exit (1);
+ emacs_perror (pty_name);
+ _exit (EXIT_CANCELED);
}
}
@@ -1995,12 +2008,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
SETUP_SLAVE_PTY;
}
#endif /* SETUP_SLAVE_PTY */
-#ifdef AIX
- /* On AIX, we've disabled SIGHUP above once we start a child on a pty.
- Now reenable it in the child, so it will die when we want it to. */
- if (pty_flag)
- signal (SIGHUP, SIG_DFL);
-#endif
#endif /* HAVE_PTYS */
signal (SIGINT, SIG_DFL);
@@ -2026,6 +2033,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
/* Back in the parent process. */
+ vfork_errno = errno;
XPROCESS (process)->pid = pid;
if (pid >= 0)
XPROCESS (process)->alive = 1;
@@ -2040,6 +2048,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
emacs_close (forkin);
if (forkin != forkout && forkout >= 0)
emacs_close (forkout);
+ report_file_errno ("Doing vfork", Qnil, vfork_errno);
}
else
{
@@ -2085,10 +2094,6 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
}
#endif
}
-
- /* Now generate the error if vfork failed. */
- if (pid < 0)
- report_file_error ("Doing vfork", Qnil);
}
void
@@ -3323,7 +3328,8 @@ usage: (make-network-process &rest ARGS) */)
retry_connect:
#endif
- s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
+ s = socket (lres->ai_family, lres->ai_socktype | SOCK_CLOEXEC,
+ lres->ai_protocol);
if (s < 0)
{
xerrno = errno;
@@ -3447,12 +3453,11 @@ usage: (make-network-process &rest ARGS) */)
len = sizeof xerrno;
eassert (FD_ISSET (s, &fdset));
- if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1)
+ if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0)
report_file_error ("getsockopt failed", Qnil);
if (xerrno)
- errno = xerrno, report_file_error ("error during connect", Qnil);
- else
- break;
+ report_file_errno ("error during connect", Qnil, xerrno);
+ break;
}
#endif /* !WINDOWSNT */
@@ -3536,11 +3541,10 @@ usage: (make-network-process &rest ARGS) */)
if (is_non_blocking_client)
return Qnil;
- errno = xerrno;
- if (is_server)
- report_file_error ("make server process failed", contact);
- else
- report_file_error ("make client process failed", contact);
+ report_file_errno ((is_server
+ ? "make server process failed"
+ : "make client process failed"),
+ contact, xerrno);
}
inch = s;
@@ -3713,7 +3717,7 @@ format; see the description of ADDRESS in `make-network-process'. */)
int s;
Lisp_Object res;
- s = socket (AF_INET, SOCK_STREAM, 0);
+ s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (s < 0)
return Qnil;
@@ -3724,14 +3728,14 @@ format; see the description of ADDRESS in `make-network-process'. */)
ifconf.ifc_len = buf_size;
if (ioctl (s, SIOCGIFCONF, &ifconf))
{
- close (s);
+ emacs_close (s);
xfree (buf);
return Qnil;
}
}
while (ifconf.ifc_len == buf_size);
- close (s);
+ emacs_close (s);
res = Qnil;
ifreq = ifconf.ifc_req;
@@ -3869,7 +3873,7 @@ FLAGS is the current flags of the interface. */)
error ("interface name too long");
strcpy (rq.ifr_name, SSDATA (ifname));
- s = socket (AF_INET, SOCK_STREAM, 0);
+ s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (s < 0)
return Qnil;
@@ -3988,7 +3992,7 @@ FLAGS is the current flags of the interface. */)
#endif
res = Fcons (elt, res);
- close (s);
+ emacs_close (s);
return any ? res : Qnil;
}
@@ -4161,7 +4165,7 @@ server_accept_connection (Lisp_Object server, int channel)
} saddr;
socklen_t len = sizeof saddr;
- s = accept (channel, &saddr.sa, &len);
+ s = accept4 (channel, &saddr.sa, &len, SOCK_CLOEXEC);
if (s < 0)
{
@@ -4785,20 +4789,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (xerrno == EINTR)
no_avail = 1;
else if (xerrno == EBADF)
- {
-#ifdef AIX
- /* AIX doesn't handle PTY closure the same way BSD does. On AIX,
- the child's closure of the pts gives the parent a SIGHUP, and
- the ptc file descriptor is automatically closed,
- yielding EBADF here or at select() call above.
- So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
- in m/ibmrt-aix.h), and here we just ignore the select error.
- Cleanup occurs c/o status_notify after SIGCHLD. */
- no_avail = 1; /* Cannot depend on values returned */
-#else
- emacs_abort ();
-#endif
- }
+ emacs_abort ();
else
error ("select error: %s", emacs_strerror (xerrno));
}
@@ -5648,7 +5639,7 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
written = emacs_gnutls_write (p, cur_buf, cur_len);
else
#endif
- written = emacs_write (outfd, cur_buf, cur_len);
+ written = emacs_write_sig (outfd, cur_buf, cur_len);
rv = (written ? 0 : -1);
#ifdef ADAPTIVE_READ_BUFFERING
if (p->read_output_delay > 0
@@ -7010,32 +7001,6 @@ setup_process_coding_systems (Lisp_Object process)
#endif
}
-/* Close all descriptors currently in use for communication
- with subprocess. This is used in a newly-forked subprocess
- to get rid of irrelevant descriptors. */
-
-void
-close_process_descs (void)
-{
-#ifndef DOS_NT
- int i;
- for (i = 0; i < MAXDESC; i++)
- {
- Lisp_Object process;
- process = chan_process[i];
- if (!NILP (process))
- {
- int in = XPROCESS (process)->infd;
- int out = XPROCESS (process)->outfd;
- if (in >= 0)
- emacs_close (in);
- if (out >= 0 && in != out)
- emacs_close (out);
- }
- }
-#endif
-}
-
DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
doc: /* Return the (or a) process associated with BUFFER.
BUFFER may be a buffer or the name of one. */)