diff options
Diffstat (limited to 'src/process.c')
-rw-r--r-- | src/process.c | 136 |
1 files changed, 80 insertions, 56 deletions
diff --git a/src/process.c b/src/process.c index bccc3ac3992..6ba27a33f4d 100644 --- a/src/process.c +++ b/src/process.c @@ -160,6 +160,18 @@ static bool kbd_is_on_hold; when exiting. */ bool inhibit_sentinels; +union u_sockaddr +{ + struct sockaddr sa; + struct sockaddr_in in; +#ifdef AF_INET6 + struct sockaddr_in6 in6; +#endif +#ifdef HAVE_LOCAL_SOCKETS + struct sockaddr_un un; +#endif +}; + #ifdef subprocesses #ifndef SOCK_CLOEXEC @@ -1248,10 +1260,7 @@ passed to the filter. The filter gets two arguments: the process and the string of output. The string argument is normally a multibyte string, except: - if the process's input coding system is no-conversion or raw-text, - it is a unibyte string (the non-converted input), or else -- if `default-enable-multibyte-characters' is nil, it is a unibyte - string (the result of converting the decoded input multibyte - string to unibyte with `string-make-unibyte'). */) + it is a unibyte string (the non-converted input). */) (Lisp_Object process, Lisp_Object filter) { CHECK_PROCESS (process); @@ -3759,8 +3768,7 @@ The stopped state is cleared by `continue-process' and set by :filter-multibyte BOOL -- If BOOL is non-nil, strings given to the process filter are multibyte, otherwise they are unibyte. -If this keyword is not specified, the strings are multibyte if -the default value of `enable-multibyte-characters' is non-nil. +If this keyword is not specified, the strings are multibyte. :sentinel SENTINEL -- Install SENTINEL as the process sentinel. @@ -3837,7 +3845,6 @@ usage: (make-network-process &rest ARGS) */) Lisp_Object contact; struct Lisp_Process *p; const char *portstring UNINIT; - ptrdiff_t portstringlen ATTRIBUTE_UNUSED; char portbuf[INT_BUFSIZE_BOUND (EMACS_INT)]; #ifdef HAVE_LOCAL_SOCKETS struct sockaddr_un address_un; @@ -3984,6 +3991,8 @@ usage: (make-network-process &rest ARGS) */) if (!NILP (host)) { + ptrdiff_t portstringlen ATTRIBUTE_UNUSED; + /* SERVICE can either be a string or int. Convert to a C string for later use by getaddrinfo. */ if (EQ (service, Qt)) @@ -4002,37 +4011,38 @@ usage: (make-network-process &rest ARGS) */) portstring = SSDATA (service); portstringlen = SBYTES (service); } - } #ifdef HAVE_GETADDRINFO_A - if (!NILP (host) && !NILP (Fplist_get (contact, QCnowait))) - { - ptrdiff_t hostlen = SBYTES (host); - struct req - { - struct gaicb gaicb; - struct addrinfo hints; - char str[FLEXIBLE_ARRAY_MEMBER]; - } *req = xmalloc (FLEXSIZEOF (struct req, str, - hostlen + 1 + portstringlen + 1)); - dns_request = &req->gaicb; - dns_request->ar_name = req->str; - dns_request->ar_service = req->str + hostlen + 1; - dns_request->ar_request = &req->hints; - dns_request->ar_result = NULL; - memset (&req->hints, 0, sizeof req->hints); - req->hints.ai_family = family; - req->hints.ai_socktype = socktype; - strcpy (req->str, SSDATA (host)); - strcpy (req->str + hostlen + 1, portstring); - - int ret = getaddrinfo_a (GAI_NOWAIT, &dns_request, 1, NULL); - if (ret) - error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret); - - goto open_socket; - } + if (!NILP (Fplist_get (contact, QCnowait))) + { + ptrdiff_t hostlen = SBYTES (host); + struct req + { + struct gaicb gaicb; + struct addrinfo hints; + char str[FLEXIBLE_ARRAY_MEMBER]; + } *req = xmalloc (FLEXSIZEOF (struct req, str, + hostlen + 1 + portstringlen + 1)); + dns_request = &req->gaicb; + dns_request->ar_name = req->str; + dns_request->ar_service = req->str + hostlen + 1; + dns_request->ar_request = &req->hints; + dns_request->ar_result = NULL; + memset (&req->hints, 0, sizeof req->hints); + req->hints.ai_family = family; + req->hints.ai_socktype = socktype; + strcpy (req->str, SSDATA (host)); + strcpy (req->str + hostlen + 1, portstring); + + int ret = getaddrinfo_a (GAI_NOWAIT, &dns_request, 1, NULL); + if (ret) + error ("%s/%s getaddrinfo_a error %d", + SSDATA (host), portstring, ret); + + goto open_socket; + } #endif /* HAVE_GETADDRINFO_A */ + } /* If we have a host, use getaddrinfo to resolve both host and service. Otherwise, use getservbyname to lookup the service. */ @@ -4675,16 +4685,7 @@ server_accept_connection (Lisp_Object server, int channel) struct Lisp_Process *ps = XPROCESS (server); struct Lisp_Process *p; int s; - union u_sockaddr { - struct sockaddr sa; - struct sockaddr_in in; -#ifdef AF_INET6 - struct sockaddr_in6 in6; -#endif -#ifdef HAVE_LOCAL_SOCKETS - struct sockaddr_un un; -#endif - } saddr; + union u_sockaddr saddr; socklen_t len = sizeof saddr; ptrdiff_t count; @@ -5005,6 +5006,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct timespec got_output_end_time = invalid_timespec (); enum { MINIMUM = -1, TIMEOUT, INFINITY } wait; int got_some_output = -1; + uintmax_t prev_wait_proc_nbytes_read = wait_proc ? wait_proc->nbytes_read : 0; #if defined HAVE_GETADDRINFO_A || defined HAVE_GNUTLS bool retry_for_async; #endif @@ -5459,6 +5461,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (nfds == 0) { /* Exit the main loop if we've passed the requested timeout, + or have read some bytes from our wait_proc (either directly + in this call or indirectly through timers / process filters), or aren't skipping processes and got some output and haven't lowered our timeout due to timers or SIGIO and have waited a long amount of time due to repeated @@ -5466,7 +5470,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, struct timespec huge_timespec = make_timespec (TYPE_MAXIMUM (time_t), 2 * TIMESPEC_RESOLUTION); struct timespec cmp_time = huge_timespec; - if (wait < TIMEOUT) + if (wait < TIMEOUT + || (wait_proc + && wait_proc->nbytes_read != prev_wait_proc_nbytes_read)) break; if (wait == TIMEOUT) cmp_time = end_time; @@ -5627,16 +5633,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, } else if (nread == -1 && would_block (errno)) ; -#ifdef WINDOWSNT - /* FIXME: Is this special case still needed? */ - /* Note that we cannot distinguish between no input - available now and a closed pipe. - With luck, a closed pipe will be accompanied by - subprocess termination and SIGCHLD. */ - else if (nread == 0 && !NETCONN_P (proc) && !SERIALCONN_P (proc) - && !PIPECONN_P (proc)) - ; -#endif #ifdef HAVE_PTYS /* On some OSs with ptys, when the process on one end of a pty exits, the other end gets an error reading with @@ -5781,6 +5777,15 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, maybe_quit (); } + /* Timers and/or process filters that we have run could have themselves called + `accept-process-output' (and by that indirectly this function), thus + possibly reading some (or all) output of wait_proc without us noticing it. + This could potentially lead to an endless wait (dealt with earlier in the + function) and/or a wrong return value (dealt with here). */ + if (wait_proc && wait_proc->nbytes_read != prev_wait_proc_nbytes_read) + got_some_output = min (INT_MAX, (wait_proc->nbytes_read + - prev_wait_proc_nbytes_read)); + return got_some_output; } @@ -5899,6 +5904,9 @@ read_process_output (Lisp_Object proc, int channel) coding->mode |= CODING_MODE_LAST_BLOCK; } + /* Ignore carryover, it's been added by a previous iteration already. */ + p->nbytes_read += nbytes; + /* Now set NBYTES how many bytes we must decode. */ nbytes += carryover; @@ -8022,6 +8030,18 @@ init_process_emacs (int sockfd) #endif external_sock_fd = sockfd; + Lisp_Object sockname = Qnil; +# if HAVE_GETSOCKNAME + if (0 <= sockfd) + { + union u_sockaddr sa; + socklen_t salen = sizeof sa; + if (getsockname (sockfd, &sa.sa, &salen) == 0) + sockname = conv_sockaddr_to_lisp (&sa.sa, salen); + } +# endif + Vinternal__daemon_sockname = sockname; + max_desc = -1; memset (fd_callback_info, 0, sizeof (fd_callback_info)); @@ -8214,6 +8234,10 @@ These functions are called in the order of the list, until one of them returns non-`nil'. */); Vinterrupt_process_functions = list1 (Qinternal_default_interrupt_process); + DEFVAR_LISP ("internal--daemon-sockname", Vinternal__daemon_sockname, + doc: /* Name of external socket passed to Emacs, or nil if none. */); + Vinternal__daemon_sockname = Qnil; + DEFSYM (Qinternal_default_interrupt_process, "internal-default-interrupt-process"); DEFSYM (Qinterrupt_process_functions, "interrupt-process-functions"); |