aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
diff options
context:
space:
mode:
authorPhilipp Stephani2020-12-24 15:27:45 +0100
committerPhilipp Stephani2020-12-24 15:34:23 +0100
commitbf7041a6f6ea2d57f842b9b2915cc58a90b01406 (patch)
tree30576ef17b8ab3ba1514fd67e303635d21fa286e /src/process.c
parent3096437593ca6d1ea07809f7d0e2198705f20e55 (diff)
downloademacs-bf7041a6f6ea2d57f842b9b2915cc58a90b01406.tar.gz
emacs-bf7041a6f6ea2d57f842b9b2915cc58a90b01406.zip
Centralize subprocess creation in a single function.
Getting the vfork + execve combination right isn't easy, and the code was partially duplicated between callproc.c and process.c. Centralize the spawn operation in a single function that deals with the nasty details. Going forward, we should be able to use posix_spawn from either libc or Gnulib (or CreateProcessW on Windows) in the non-pty case. * src/callproc.c (emacs_spawn): New function to start an asynchronous subprocess. Merge code from 'call_process' and 'create_process' into this function. (call_process): Use new 'emacs_spawn' function. (child_setup): Make static, since there are no users outside this compilation unit left. (CHILD_SETUP_TYPE): Move from header file, since there are no users outside this compilation unit left. * src/process.c (create_process): Use new 'emacs_spawn' function.
Diffstat (limited to 'src/process.c')
-rw-r--r--src/process.c149
1 files changed, 7 insertions, 142 deletions
diff --git a/src/process.c b/src/process.c
index 15b4a23784e..f3de9251b7a 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2047,13 +2047,12 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2047{ 2047{
2048 struct Lisp_Process *p = XPROCESS (process); 2048 struct Lisp_Process *p = XPROCESS (process);
2049 int inchannel, outchannel; 2049 int inchannel, outchannel;
2050 pid_t pid; 2050 pid_t pid = -1;
2051 int vfork_errno; 2051 int vfork_errno;
2052 int forkin, forkout, forkerr = -1; 2052 int forkin, forkout, forkerr = -1;
2053 bool pty_flag = 0; 2053 bool pty_flag = 0;
2054 char pty_name[PTY_NAME_SIZE]; 2054 char pty_name[PTY_NAME_SIZE];
2055 Lisp_Object lisp_pty_name = Qnil; 2055 Lisp_Object lisp_pty_name = Qnil;
2056 sigset_t oldset;
2057 2056
2058 inchannel = outchannel = -1; 2057 inchannel = outchannel = -1;
2059 2058
@@ -2130,154 +2129,20 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2130 setup_process_coding_systems (process); 2129 setup_process_coding_systems (process);
2131 char *const *env = make_environment_block (current_dir); 2130 char *const *env = make_environment_block (current_dir);
2132 2131
2133 block_input ();
2134 block_child_signal (&oldset);
2135
2136#ifndef WINDOWSNT
2137 /* vfork, and prevent local vars from being clobbered by the vfork. */
2138 Lisp_Object volatile current_dir_volatile = current_dir;
2139 Lisp_Object volatile lisp_pty_name_volatile = lisp_pty_name;
2140 char **volatile new_argv_volatile = new_argv;
2141 int volatile forkin_volatile = forkin;
2142 int volatile forkout_volatile = forkout;
2143 int volatile forkerr_volatile = forkerr;
2144 struct Lisp_Process *p_volatile = p;
2145 char *const *volatile env_volatile = env;
2146
2147#ifdef DARWIN_OS
2148 /* Darwin doesn't let us run setsid after a vfork, so use fork when
2149 necessary. Also, reset SIGCHLD handling after a vfork, as
2150 apparently macOS can mistakenly deliver SIGCHLD to the child. */
2151 if (pty_flag)
2152 pid = fork ();
2153 else
2154 {
2155 pid = vfork ();
2156 if (pid == 0)
2157 signal (SIGCHLD, SIG_DFL);
2158 }
2159#else
2160 pid = vfork ();
2161#endif
2162
2163 current_dir = current_dir_volatile;
2164 lisp_pty_name = lisp_pty_name_volatile;
2165 new_argv = new_argv_volatile;
2166 forkin = forkin_volatile;
2167 forkout = forkout_volatile;
2168 forkerr = forkerr_volatile;
2169 p = p_volatile;
2170 env = env_volatile;
2171
2172 pty_flag = p->pty_flag; 2132 pty_flag = p->pty_flag;
2133 eassert (pty_flag == ! NILP (lisp_pty_name));
2173 2134
2174 if (pid == 0) 2135 vfork_errno
2175#endif /* not WINDOWSNT */ 2136 = emacs_spawn (&pid, forkin, forkout, forkerr, new_argv, env,
2176 { 2137 SSDATA (current_dir),
2177 /* Make the pty be the controlling terminal of the process. */ 2138 pty_flag ? SSDATA (lisp_pty_name) : NULL);
2178#ifdef HAVE_PTYS
2179 dissociate_controlling_tty ();
2180 2139
2181 /* Make the pty's terminal the controlling terminal. */ 2140 eassert ((vfork_errno == 0) == (0 < pid));
2182 if (pty_flag && forkin >= 0)
2183 {
2184#ifdef TIOCSCTTY
2185 /* We ignore the return value
2186 because faith@cs.unc.edu says that is necessary on Linux. */
2187 ioctl (forkin, TIOCSCTTY, 0);
2188#endif
2189 }
2190#if defined (LDISC1)
2191 if (pty_flag && forkin >= 0)
2192 {
2193 struct termios t;
2194 tcgetattr (forkin, &t);
2195 t.c_lflag = LDISC1;
2196 if (tcsetattr (forkin, TCSANOW, &t) < 0)
2197 emacs_perror ("create_process/tcsetattr LDISC1");
2198 }
2199#else
2200#if defined (NTTYDISC) && defined (TIOCSETD)
2201 if (pty_flag && forkin >= 0)
2202 {
2203 /* Use new line discipline. */
2204 int ldisc = NTTYDISC;
2205 ioctl (forkin, TIOCSETD, &ldisc);
2206 }
2207#endif
2208#endif
2209 2141
2210#if !defined (DONT_REOPEN_PTY)
2211/*** There is a suggestion that this ought to be a
2212 conditional on TIOCSPGRP, or !defined TIOCSCTTY.
2213 Trying the latter gave the wrong results on Debian GNU/Linux 1.1;
2214 that system does seem to need this code, even though
2215 both TIOCSCTTY is defined. */
2216 /* Now close the pty (if we had it open) and reopen it.
2217 This makes the pty the controlling terminal of the subprocess. */
2218 if (pty_flag)
2219 {
2220
2221 /* I wonder if emacs_close (emacs_open (SSDATA (lisp_pty_name), ...))
2222 would work? */
2223 if (forkin >= 0)
2224 emacs_close (forkin);
2225 forkout = forkin = emacs_open (SSDATA (lisp_pty_name), O_RDWR, 0);
2226
2227 if (forkin < 0)
2228 {
2229 emacs_perror (SSDATA (lisp_pty_name));
2230 _exit (EXIT_CANCELED);
2231 }
2232
2233 }
2234#endif /* not DONT_REOPEN_PTY */
2235
2236#ifdef SETUP_SLAVE_PTY
2237 if (pty_flag)
2238 {
2239 SETUP_SLAVE_PTY;
2240 }
2241#endif /* SETUP_SLAVE_PTY */
2242#endif /* HAVE_PTYS */
2243
2244 signal (SIGINT, SIG_DFL);
2245 signal (SIGQUIT, SIG_DFL);
2246#ifdef SIGPROF
2247 signal (SIGPROF, SIG_DFL);
2248#endif
2249
2250 /* Emacs ignores SIGPIPE, but the child should not. */
2251 signal (SIGPIPE, SIG_DFL);
2252
2253 /* Stop blocking SIGCHLD in the child. */
2254 unblock_child_signal (&oldset);
2255
2256 if (pty_flag)
2257 child_setup_tty (forkout);
2258
2259 if (forkerr < 0)
2260 forkerr = forkout;
2261#ifdef WINDOWSNT
2262 pid = child_setup (forkin, forkout, forkerr, new_argv, env,
2263 SSDATA (current_dir));
2264#else /* not WINDOWSNT */
2265 child_setup (forkin, forkout, forkerr, new_argv, env,
2266 SSDATA (current_dir));
2267#endif /* not WINDOWSNT */
2268 }
2269
2270 /* Back in the parent process. */
2271
2272 vfork_errno = errno;
2273 p->pid = pid; 2142 p->pid = pid;
2274 if (pid >= 0) 2143 if (pid >= 0)
2275 p->alive = 1; 2144 p->alive = 1;
2276 2145
2277 /* Stop blocking in the parent. */
2278 unblock_child_signal (&oldset);
2279 unblock_input ();
2280
2281 /* Environment block no longer needed. */ 2146 /* Environment block no longer needed. */
2282 unbind_to (count, Qnil); 2147 unbind_to (count, Qnil);
2283 2148