aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-08-11 11:24:54 -0700
committerPaul Eggert2016-08-11 11:26:34 -0700
commit2dd8044bfb61efc368c590b1285fdbca54606152 (patch)
treee080593b4e2183d66aeaaa6a0c406577f32a129a /src
parent2e0a2b376f51dd515ffeb6449181cc37fe912f5e (diff)
downloademacs-2dd8044bfb61efc368c590b1285fdbca54606152.tar.gz
emacs-2dd8044bfb61efc368c590b1285fdbca54606152.zip
Fix process leak with make-network-process
This problem was introduced by the recent async changes (Bug#23808). * src/process.c (Fmake_process): Move USE_SAFE_ALLOCA later, so that it follows the start_process_unwind unwind-protect. Set pid to -1 while the process is being created. (start_process_unwind): Omit unnecessary emacs_abort test. (connect_network_socket): Simplify use of counts. Unwind bind_polling_period a bit earlier, so that a remove_process unwind-protect can be added when needed; this is the heart of the fix. Undo the unwind-protect just before returning.
Diffstat (limited to 'src')
-rw-r--r--src/process.c49
-rw-r--r--src/process.h9
2 files changed, 23 insertions, 35 deletions
diff --git a/src/process.c b/src/process.c
index fb326982e5d..69d1b2a11ba 100644
--- a/src/process.c
+++ b/src/process.c
@@ -238,6 +238,7 @@ static int process_output_delay_count;
238 238
239static bool process_output_skip; 239static bool process_output_skip;
240 240
241static void start_process_unwind (Lisp_Object);
241static void create_process (Lisp_Object, char **, Lisp_Object); 242static void create_process (Lisp_Object, char **, Lisp_Object);
242#ifdef USABLE_SIGIO 243#ifdef USABLE_SIGIO
243static bool keyboard_bit_set (fd_set *); 244static bool keyboard_bit_set (fd_set *);
@@ -245,11 +246,8 @@ static bool keyboard_bit_set (fd_set *);
245static void deactivate_process (Lisp_Object); 246static void deactivate_process (Lisp_Object);
246static int status_notify (struct Lisp_Process *, struct Lisp_Process *); 247static int status_notify (struct Lisp_Process *, struct Lisp_Process *);
247static int read_process_output (Lisp_Object, int); 248static int read_process_output (Lisp_Object, int);
248static void handle_child_signal (int);
249static void create_pty (Lisp_Object); 249static void create_pty (Lisp_Object);
250 250static void exec_sentinel (Lisp_Object, Lisp_Object);
251static Lisp_Object get_process (register Lisp_Object name);
252static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
253 251
254/* Mask of bits indicating the descriptors that we wait for input on. */ 252/* Mask of bits indicating the descriptors that we wait for input on. */
255 253
@@ -1407,8 +1405,6 @@ DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
1407 1405
1408/* Starting asynchronous inferior processes. */ 1406/* Starting asynchronous inferior processes. */
1409 1407
1410static void start_process_unwind (Lisp_Object proc);
1411
1412DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0, 1408DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0,
1413 doc: /* Start a program in a subprocess. Return the process object for it. 1409 doc: /* Start a program in a subprocess. Return the process object for it.
1414 1410
@@ -1459,7 +1455,6 @@ usage: (make-process &rest ARGS) */)
1459 Lisp_Object buffer, name, command, program, proc, contact, current_dir, tem; 1455 Lisp_Object buffer, name, command, program, proc, contact, current_dir, tem;
1460 Lisp_Object xstderr, stderrproc; 1456 Lisp_Object xstderr, stderrproc;
1461 ptrdiff_t count = SPECPDL_INDEX (); 1457 ptrdiff_t count = SPECPDL_INDEX ();
1462 USE_SAFE_ALLOCA;
1463 1458
1464 if (nargs == 0) 1459 if (nargs == 0)
1465 return Qnil; 1460 return Qnil;
@@ -1508,10 +1503,6 @@ usage: (make-process &rest ARGS) */)
1508 } 1503 }
1509 1504
1510 proc = make_process (name); 1505 proc = make_process (name);
1511 /* If an error occurs and we can't start the process, we want to
1512 remove it from the process list. This means that each error
1513 check in create_process doesn't need to call remove_process
1514 itself; it's all taken care of here. */
1515 record_unwind_protect (start_process_unwind, proc); 1506 record_unwind_protect (start_process_unwind, proc);
1516 1507
1517 pset_childp (XPROCESS (proc), Qt); 1508 pset_childp (XPROCESS (proc), Qt);
@@ -1561,6 +1552,8 @@ usage: (make-process &rest ARGS) */)
1561 BUF_ZV (XBUFFER (buffer)), 1552 BUF_ZV (XBUFFER (buffer)),
1562 BUF_ZV_BYTE (XBUFFER (buffer))); 1553 BUF_ZV_BYTE (XBUFFER (buffer)));
1563 1554
1555 USE_SAFE_ALLOCA;
1556
1564 { 1557 {
1565 /* Decide coding systems for communicating with the process. Here 1558 /* Decide coding systems for communicating with the process. Here
1566 we don't setup the structure coding_system nor pay attention to 1559 we don't setup the structure coding_system nor pay attention to
@@ -1719,18 +1712,11 @@ usage: (make-process &rest ARGS) */)
1719 return unbind_to (count, proc); 1712 return unbind_to (count, proc);
1720} 1713}
1721 1714
1722/* This function is the unwind_protect form for Fstart_process. If 1715/* If PROC doesn't have its pid set, then an error was signaled and
1723 PROC doesn't have its pid set, then we know someone has signaled 1716 the process wasn't started successfully, so remove it. */
1724 an error and the process wasn't started successfully, so we should
1725 remove it from the process list. */
1726static void 1717static void
1727start_process_unwind (Lisp_Object proc) 1718start_process_unwind (Lisp_Object proc)
1728{ 1719{
1729 if (!PROCESSP (proc))
1730 emacs_abort ();
1731
1732 /* Was PROC started successfully?
1733 -2 is used for a pty with no process, eg for gdb. */
1734 if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2) 1720 if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2)
1735 remove_process (proc); 1721 remove_process (proc);
1736} 1722}
@@ -3124,7 +3110,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3124 Lisp_Object use_external_socket_p) 3110 Lisp_Object use_external_socket_p)
3125{ 3111{
3126 ptrdiff_t count = SPECPDL_INDEX (); 3112 ptrdiff_t count = SPECPDL_INDEX ();
3127 ptrdiff_t count1;
3128 int s = -1, outch, inch; 3113 int s = -1, outch, inch;
3129 int xerrno = 0; 3114 int xerrno = 0;
3130 int family; 3115 int family;
@@ -3145,7 +3130,6 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3145 } 3130 }
3146 3131
3147 /* Do this in case we never enter the while-loop below. */ 3132 /* Do this in case we never enter the while-loop below. */
3148 count1 = SPECPDL_INDEX ();
3149 s = -1; 3133 s = -1;
3150 3134
3151 while (!NILP (addrinfos)) 3135 while (!NILP (addrinfos))
@@ -3313,7 +3297,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3313 immediate_quit = 0; 3297 immediate_quit = 0;
3314 3298
3315 /* Discard the unwind protect closing S. */ 3299 /* Discard the unwind protect closing S. */
3316 specpdl_ptr = specpdl + count1; 3300 specpdl_ptr = specpdl + count;
3317 emacs_close (s); 3301 emacs_close (s);
3318 s = -1; 3302 s = -1;
3319 if (0 <= socket_to_use) 3303 if (0 <= socket_to_use)
@@ -3398,10 +3382,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3398 p->outfd = outch; 3382 p->outfd = outch;
3399 3383
3400 /* Discard the unwind protect for closing S, if any. */ 3384 /* Discard the unwind protect for closing S, if any. */
3401 specpdl_ptr = specpdl + count1; 3385 specpdl_ptr = specpdl + count;
3402
3403 /* Unwind bind_polling_period and request_sigio. */
3404 unbind_to (count, Qnil);
3405 3386
3406 if (p->is_server && p->socktype != SOCK_DGRAM) 3387 if (p->is_server && p->socktype != SOCK_DGRAM)
3407 pset_status (p, Qlisten); 3388 pset_status (p, Qlisten);
@@ -3925,7 +3906,12 @@ usage: (make-network-process &rest ARGS) */)
3925 3906
3926 if (!NILP (buffer)) 3907 if (!NILP (buffer))
3927 buffer = Fget_buffer_create (buffer); 3908 buffer = Fget_buffer_create (buffer);
3909
3910 /* Unwind bind_polling_period. */
3911 unbind_to (count, Qnil);
3912
3928 proc = make_process (name); 3913 proc = make_process (name);
3914 record_unwind_protect (remove_process, proc);
3929 p = XPROCESS (proc); 3915 p = XPROCESS (proc);
3930 pset_childp (p, contact); 3916 pset_childp (p, contact);
3931 pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); 3917 pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist)));
@@ -3956,8 +3942,6 @@ usage: (make-network-process &rest ARGS) */)
3956 3942
3957 set_network_socket_coding_system (proc, host, service, name); 3943 set_network_socket_coding_system (proc, host, service, name);
3958 3944
3959 unbind_to (count, Qnil);
3960
3961 /* :server BOOL */ 3945 /* :server BOOL */
3962 tem = Fplist_get (contact, QCserver); 3946 tem = Fplist_get (contact, QCserver);
3963 if (!NILP (tem)) 3947 if (!NILP (tem))
@@ -3974,6 +3958,7 @@ usage: (make-network-process &rest ARGS) */)
3974 && !NILP (Fplist_get (contact, QCnowait))) 3958 && !NILP (Fplist_get (contact, QCnowait)))
3975 p->is_non_blocking_client = true; 3959 p->is_non_blocking_client = true;
3976 3960
3961 bool postpone_connection = false;
3977#ifdef HAVE_GETADDRINFO_A 3962#ifdef HAVE_GETADDRINFO_A
3978 /* With async address resolution, the list of addresses is empty, so 3963 /* With async address resolution, the list of addresses is empty, so
3979 postpone connecting to the server. */ 3964 postpone connecting to the server. */
@@ -3981,11 +3966,13 @@ usage: (make-network-process &rest ARGS) */)
3981 { 3966 {
3982 p->dns_request = dns_request; 3967 p->dns_request = dns_request;
3983 p->status = list1 (Qconnect); 3968 p->status = list1 (Qconnect);
3984 return proc; 3969 postpone_connection = true;
3985 } 3970 }
3986#endif 3971#endif
3972 if (! postpone_connection)
3973 connect_network_socket (proc, addrinfos, use_external_socket_p);
3987 3974
3988 connect_network_socket (proc, addrinfos, use_external_socket_p); 3975 specpdl_ptr = specpdl + count;
3989 return proc; 3976 return proc;
3990} 3977}
3991 3978
diff --git a/src/process.h b/src/process.h
index 6c227bc2266..9926050b9c3 100644
--- a/src/process.h
+++ b/src/process.h
@@ -118,10 +118,11 @@ struct Lisp_Process
118 /* After this point, there are no Lisp_Objects any more. */ 118 /* After this point, there are no Lisp_Objects any more. */
119 /* alloc.c assumes that `pid' is the first such non-Lisp slot. */ 119 /* alloc.c assumes that `pid' is the first such non-Lisp slot. */
120 120
121 /* Number of this process. 121 /* Process ID. A positive value is a child process ID.
122 allocate_process assumes this is the first non-Lisp_Object field. 122 Zero is for pseudo-processes such as network or serial connections,
123 A value 0 is used for pseudo-processes such as network or serial 123 or for processes that have not been fully created yet.
124 connections. */ 124 -1 is for a process that was not created successfully.
125 -2 is for a pty with no process, e.g., for GDB. */
125 pid_t pid; 126 pid_t pid;
126 /* Descriptor by which we read from this process. */ 127 /* Descriptor by which we read from this process. */
127 int infd; 128 int infd;