diff options
| author | Paul Eggert | 2016-08-11 11:24:54 -0700 |
|---|---|---|
| committer | Paul Eggert | 2016-08-11 11:26:34 -0700 |
| commit | 2dd8044bfb61efc368c590b1285fdbca54606152 (patch) | |
| tree | e080593b4e2183d66aeaaa6a0c406577f32a129a /src | |
| parent | 2e0a2b376f51dd515ffeb6449181cc37fe912f5e (diff) | |
| download | emacs-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.c | 49 | ||||
| -rw-r--r-- | src/process.h | 9 |
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 | ||
| 239 | static bool process_output_skip; | 239 | static bool process_output_skip; |
| 240 | 240 | ||
| 241 | static void start_process_unwind (Lisp_Object); | ||
| 241 | static void create_process (Lisp_Object, char **, Lisp_Object); | 242 | static void create_process (Lisp_Object, char **, Lisp_Object); |
| 242 | #ifdef USABLE_SIGIO | 243 | #ifdef USABLE_SIGIO |
| 243 | static bool keyboard_bit_set (fd_set *); | 244 | static bool keyboard_bit_set (fd_set *); |
| @@ -245,11 +246,8 @@ static bool keyboard_bit_set (fd_set *); | |||
| 245 | static void deactivate_process (Lisp_Object); | 246 | static void deactivate_process (Lisp_Object); |
| 246 | static int status_notify (struct Lisp_Process *, struct Lisp_Process *); | 247 | static int status_notify (struct Lisp_Process *, struct Lisp_Process *); |
| 247 | static int read_process_output (Lisp_Object, int); | 248 | static int read_process_output (Lisp_Object, int); |
| 248 | static void handle_child_signal (int); | ||
| 249 | static void create_pty (Lisp_Object); | 249 | static void create_pty (Lisp_Object); |
| 250 | 250 | static void exec_sentinel (Lisp_Object, Lisp_Object); | |
| 251 | static Lisp_Object get_process (register Lisp_Object name); | ||
| 252 | static 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 | ||
| 1410 | static void start_process_unwind (Lisp_Object proc); | ||
| 1411 | |||
| 1412 | DEFUN ("make-process", Fmake_process, Smake_process, 0, MANY, 0, | 1408 | DEFUN ("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. */ | ||
| 1726 | static void | 1717 | static void |
| 1727 | start_process_unwind (Lisp_Object proc) | 1718 | start_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; |