diff options
| author | Vincent Belaïche | 2016-07-28 18:12:50 +0200 |
|---|---|---|
| committer | Vincent Belaïche | 2016-07-28 18:12:50 +0200 |
| commit | 90ab699c4f281d0c9a9b71f3eb4c8493d00fcf4f (patch) | |
| tree | df3235d89ee8e4d32571b8a8521f75f7576913c2 /src/process.c | |
| parent | 41b28dea8587c13b0bc59c1ec70b65afab3aeeca (diff) | |
| parent | ec359399a47f852b4d022a30245449438e349193 (diff) | |
| download | emacs-90ab699c4f281d0c9a9b71f3eb4c8493d00fcf4f.tar.gz emacs-90ab699c4f281d0c9a9b71f3eb4c8493d00fcf4f.zip | |
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src/process.c')
| -rw-r--r-- | src/process.c | 110 |
1 files changed, 72 insertions, 38 deletions
diff --git a/src/process.c b/src/process.c index 9ca3e594355..bc2ac451c9d 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -130,10 +130,10 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *, | |||
| 130 | struct timespec *, void *); | 130 | struct timespec *, void *); |
| 131 | #endif | 131 | #endif |
| 132 | 132 | ||
| 133 | /* Work around GCC 4.7.0 bug with strict overflow checking; see | 133 | /* Work around GCC 4.3.0 bug with strict overflow checking; see |
| 134 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. | 134 | <http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52904>. |
| 135 | This bug appears to be fixed in GCC 5.1, so don't work around it there. */ | 135 | This bug appears to be fixed in GCC 5.1, so don't work around it there. */ |
| 136 | #if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 | 136 | #if GNUC_PREREQ (4, 3, 0) && ! GNUC_PREREQ (5, 1, 0) |
| 137 | # pragma GCC diagnostic ignored "-Wstrict-overflow" | 137 | # pragma GCC diagnostic ignored "-Wstrict-overflow" |
| 138 | #endif | 138 | #endif |
| 139 | 139 | ||
| @@ -533,25 +533,37 @@ status_convert (int w) | |||
| 533 | return Qrun; | 533 | return Qrun; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | /* True if STATUS is that of a process attempting connection. */ | ||
| 537 | |||
| 538 | static bool | ||
| 539 | connecting_status (Lisp_Object status) | ||
| 540 | { | ||
| 541 | return CONSP (status) && EQ (XCAR (status), Qconnect); | ||
| 542 | } | ||
| 543 | |||
| 536 | /* Given a status-list, extract the three pieces of information | 544 | /* Given a status-list, extract the three pieces of information |
| 537 | and store them individually through the three pointers. */ | 545 | and store them individually through the three pointers. */ |
| 538 | 546 | ||
| 539 | static void | 547 | static void |
| 540 | decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, bool *coredump) | 548 | decode_status (Lisp_Object l, Lisp_Object *symbol, Lisp_Object *code, |
| 549 | bool *coredump) | ||
| 541 | { | 550 | { |
| 542 | Lisp_Object tem; | 551 | Lisp_Object tem; |
| 543 | 552 | ||
| 553 | if (connecting_status (l)) | ||
| 554 | l = XCAR (l); | ||
| 555 | |||
| 544 | if (SYMBOLP (l)) | 556 | if (SYMBOLP (l)) |
| 545 | { | 557 | { |
| 546 | *symbol = l; | 558 | *symbol = l; |
| 547 | *code = 0; | 559 | *code = make_number (0); |
| 548 | *coredump = 0; | 560 | *coredump = 0; |
| 549 | } | 561 | } |
| 550 | else | 562 | else |
| 551 | { | 563 | { |
| 552 | *symbol = XCAR (l); | 564 | *symbol = XCAR (l); |
| 553 | tem = XCDR (l); | 565 | tem = XCDR (l); |
| 554 | *code = XFASTINT (XCAR (tem)); | 566 | *code = XCAR (tem); |
| 555 | tem = XCDR (tem); | 567 | tem = XCDR (tem); |
| 556 | *coredump = !NILP (tem); | 568 | *coredump = !NILP (tem); |
| 557 | } | 569 | } |
| @@ -563,8 +575,7 @@ static Lisp_Object | |||
| 563 | status_message (struct Lisp_Process *p) | 575 | status_message (struct Lisp_Process *p) |
| 564 | { | 576 | { |
| 565 | Lisp_Object status = p->status; | 577 | Lisp_Object status = p->status; |
| 566 | Lisp_Object symbol; | 578 | Lisp_Object symbol, code; |
| 567 | int code; | ||
| 568 | bool coredump; | 579 | bool coredump; |
| 569 | Lisp_Object string; | 580 | Lisp_Object string; |
| 570 | 581 | ||
| @@ -574,7 +585,7 @@ status_message (struct Lisp_Process *p) | |||
| 574 | { | 585 | { |
| 575 | char const *signame; | 586 | char const *signame; |
| 576 | synchronize_system_messages_locale (); | 587 | synchronize_system_messages_locale (); |
| 577 | signame = strsignal (code); | 588 | signame = strsignal (XFASTINT (code)); |
| 578 | if (signame == 0) | 589 | if (signame == 0) |
| 579 | string = build_string ("unknown"); | 590 | string = build_string ("unknown"); |
| 580 | else | 591 | else |
| @@ -596,20 +607,20 @@ status_message (struct Lisp_Process *p) | |||
| 596 | else if (EQ (symbol, Qexit)) | 607 | else if (EQ (symbol, Qexit)) |
| 597 | { | 608 | { |
| 598 | if (NETCONN1_P (p)) | 609 | if (NETCONN1_P (p)) |
| 599 | return build_string (code == 0 ? "deleted\n" : "connection broken by remote peer\n"); | 610 | return build_string (XFASTINT (code) == 0 |
| 600 | if (code == 0) | 611 | ? "deleted\n" |
| 612 | : "connection broken by remote peer\n"); | ||
| 613 | if (XFASTINT (code) == 0) | ||
| 601 | return build_string ("finished\n"); | 614 | return build_string ("finished\n"); |
| 602 | AUTO_STRING (prefix, "exited abnormally with code "); | 615 | AUTO_STRING (prefix, "exited abnormally with code "); |
| 603 | string = Fnumber_to_string (make_number (code)); | 616 | string = Fnumber_to_string (code); |
| 604 | AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); | 617 | AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); |
| 605 | return concat3 (prefix, string, suffix); | 618 | return concat3 (prefix, string, suffix); |
| 606 | } | 619 | } |
| 607 | else if (EQ (symbol, Qfailed)) | 620 | else if (EQ (symbol, Qfailed)) |
| 608 | { | 621 | { |
| 609 | AUTO_STRING (prefix, "failed with code "); | 622 | AUTO_STRING (format, "failed with code %s\n"); |
| 610 | string = Fnumber_to_string (make_number (code)); | 623 | return CALLN (Fformat, format, code); |
| 611 | AUTO_STRING (suffix, "\n"); | ||
| 612 | return concat3 (prefix, string, suffix); | ||
| 613 | } | 624 | } |
| 614 | else | 625 | else |
| 615 | return Fcopy_sequence (Fsymbol_name (symbol)); | 626 | return Fcopy_sequence (Fsymbol_name (symbol)); |
| @@ -3174,6 +3185,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3174 | xerrno = errno; | 3185 | xerrno = errno; |
| 3175 | emacs_close (s); | 3186 | emacs_close (s); |
| 3176 | s = -1; | 3187 | s = -1; |
| 3188 | if (socket_to_use < 0) | ||
| 3189 | break; | ||
| 3177 | continue; | 3190 | continue; |
| 3178 | } | 3191 | } |
| 3179 | } | 3192 | } |
| @@ -3288,9 +3301,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3288 | eassert (FD_ISSET (s, &fdset)); | 3301 | eassert (FD_ISSET (s, &fdset)); |
| 3289 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) | 3302 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) |
| 3290 | report_file_error ("Failed getsockopt", Qnil); | 3303 | report_file_error ("Failed getsockopt", Qnil); |
| 3291 | if (xerrno) | 3304 | if (xerrno == 0) |
| 3305 | break; | ||
| 3306 | if (NILP (addrinfos)) | ||
| 3292 | report_file_errno ("Failed connect", Qnil, xerrno); | 3307 | report_file_errno ("Failed connect", Qnil, xerrno); |
| 3293 | break; | ||
| 3294 | } | 3308 | } |
| 3295 | #endif /* !WINDOWSNT */ | 3309 | #endif /* !WINDOWSNT */ |
| 3296 | 3310 | ||
| @@ -3300,6 +3314,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3300 | specpdl_ptr = specpdl + count1; | 3314 | specpdl_ptr = specpdl + count1; |
| 3301 | emacs_close (s); | 3315 | emacs_close (s); |
| 3302 | s = -1; | 3316 | s = -1; |
| 3317 | if (socket_to_use < 0) | ||
| 3318 | break; | ||
| 3303 | 3319 | ||
| 3304 | #ifdef WINDOWSNT | 3320 | #ifdef WINDOWSNT |
| 3305 | if (xerrno == EINTR) | 3321 | if (xerrno == EINTR) |
| @@ -3399,7 +3415,9 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3399 | /* We may get here if connect did succeed immediately. However, | 3415 | /* We may get here if connect did succeed immediately. However, |
| 3400 | in that case, we still need to signal this like a non-blocking | 3416 | in that case, we still need to signal this like a non-blocking |
| 3401 | connection. */ | 3417 | connection. */ |
| 3402 | pset_status (p, Qconnect); | 3418 | if (! (connecting_status (p->status) |
| 3419 | && EQ (XCDR (p->status), addrinfos))) | ||
| 3420 | pset_status (p, Fcons (Qconnect, addrinfos)); | ||
| 3403 | if (!FD_ISSET (inch, &connect_wait_mask)) | 3421 | if (!FD_ISSET (inch, &connect_wait_mask)) |
| 3404 | { | 3422 | { |
| 3405 | FD_SET (inch, &connect_wait_mask); | 3423 | FD_SET (inch, &connect_wait_mask); |
| @@ -3960,7 +3978,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3960 | if (!p->is_server && NILP (addrinfos)) | 3978 | if (!p->is_server && NILP (addrinfos)) |
| 3961 | { | 3979 | { |
| 3962 | p->dns_request = dns_request; | 3980 | p->dns_request = dns_request; |
| 3963 | p->status = Qconnect; | 3981 | p->status = list1 (Qconnect); |
| 3964 | return proc; | 3982 | return proc; |
| 3965 | } | 3983 | } |
| 3966 | #endif | 3984 | #endif |
| @@ -4673,7 +4691,7 @@ check_for_dns (Lisp_Object proc) | |||
| 4673 | addrinfos = Fnreverse (addrinfos); | 4691 | addrinfos = Fnreverse (addrinfos); |
| 4674 | } | 4692 | } |
| 4675 | /* The DNS lookup failed. */ | 4693 | /* The DNS lookup failed. */ |
| 4676 | else if (EQ (p->status, Qconnect)) | 4694 | else if (connecting_status (p->status)) |
| 4677 | { | 4695 | { |
| 4678 | deactivate_process (proc); | 4696 | deactivate_process (proc); |
| 4679 | pset_status (p, (list2 | 4697 | pset_status (p, (list2 |
| @@ -4686,7 +4704,7 @@ check_for_dns (Lisp_Object proc) | |||
| 4686 | free_dns_request (proc); | 4704 | free_dns_request (proc); |
| 4687 | 4705 | ||
| 4688 | /* This process should not already be connected (or killed). */ | 4706 | /* This process should not already be connected (or killed). */ |
| 4689 | if (!EQ (p->status, Qconnect)) | 4707 | if (! connecting_status (p->status)) |
| 4690 | return Qnil; | 4708 | return Qnil; |
| 4691 | 4709 | ||
| 4692 | return addrinfos; | 4710 | return addrinfos; |
| @@ -4698,7 +4716,7 @@ static void | |||
| 4698 | wait_for_socket_fds (Lisp_Object process, char const *name) | 4716 | wait_for_socket_fds (Lisp_Object process, char const *name) |
| 4699 | { | 4717 | { |
| 4700 | while (XPROCESS (process)->infd < 0 | 4718 | while (XPROCESS (process)->infd < 0 |
| 4701 | && EQ (XPROCESS (process)->status, Qconnect)) | 4719 | && connecting_status (XPROCESS (process)->status)) |
| 4702 | { | 4720 | { |
| 4703 | add_to_log ("Waiting for socket from %s...", build_string (name)); | 4721 | add_to_log ("Waiting for socket from %s...", build_string (name)); |
| 4704 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); | 4722 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); |
| @@ -4708,7 +4726,7 @@ wait_for_socket_fds (Lisp_Object process, char const *name) | |||
| 4708 | static void | 4726 | static void |
| 4709 | wait_while_connecting (Lisp_Object process) | 4727 | wait_while_connecting (Lisp_Object process) |
| 4710 | { | 4728 | { |
| 4711 | while (EQ (XPROCESS (process)->status, Qconnect)) | 4729 | while (connecting_status (XPROCESS (process)->status)) |
| 4712 | { | 4730 | { |
| 4713 | add_to_log ("Waiting for connection..."); | 4731 | add_to_log ("Waiting for connection..."); |
| 4714 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); | 4732 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); |
| @@ -5010,7 +5028,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5010 | update_status (wait_proc); | 5028 | update_status (wait_proc); |
| 5011 | if (wait_proc | 5029 | if (wait_proc |
| 5012 | && ! EQ (wait_proc->status, Qrun) | 5030 | && ! EQ (wait_proc->status, Qrun) |
| 5013 | && ! EQ (wait_proc->status, Qconnect)) | 5031 | && ! connecting_status (wait_proc->status)) |
| 5014 | { | 5032 | { |
| 5015 | bool read_some_bytes = false; | 5033 | bool read_some_bytes = false; |
| 5016 | 5034 | ||
| @@ -5255,16 +5273,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5255 | haven't lowered our timeout due to timers or SIGIO and | 5273 | haven't lowered our timeout due to timers or SIGIO and |
| 5256 | have waited a long amount of time due to repeated | 5274 | have waited a long amount of time due to repeated |
| 5257 | timers. */ | 5275 | timers. */ |
| 5276 | struct timespec huge_timespec | ||
| 5277 | = make_timespec (TYPE_MAXIMUM (time_t), 2 * TIMESPEC_RESOLUTION); | ||
| 5278 | struct timespec cmp_time = huge_timespec; | ||
| 5258 | if (wait < TIMEOUT) | 5279 | if (wait < TIMEOUT) |
| 5259 | break; | 5280 | break; |
| 5260 | struct timespec cmp_time | 5281 | if (wait == TIMEOUT) |
| 5261 | = (wait == TIMEOUT | 5282 | cmp_time = end_time; |
| 5262 | ? end_time | 5283 | if (!process_skipped && got_some_output > 0 |
| 5263 | : (!process_skipped && got_some_output > 0 | 5284 | && (timeout.tv_sec > 0 || timeout.tv_nsec > 0)) |
| 5264 | && (timeout.tv_sec > 0 || timeout.tv_nsec > 0)) | 5285 | { |
| 5265 | ? got_output_end_time | 5286 | if (!timespec_valid_p (got_output_end_time)) |
| 5266 | : invalid_timespec ()); | 5287 | break; |
| 5267 | if (timespec_valid_p (cmp_time)) | 5288 | if (timespec_cmp (got_output_end_time, cmp_time) < 0) |
| 5289 | cmp_time = got_output_end_time; | ||
| 5290 | } | ||
| 5291 | if (timespec_cmp (cmp_time, huge_timespec) < 0) | ||
| 5268 | { | 5292 | { |
| 5269 | now = current_timespec (); | 5293 | now = current_timespec (); |
| 5270 | if (timespec_cmp (cmp_time, now) <= 0) | 5294 | if (timespec_cmp (cmp_time, now) <= 0) |
| @@ -5492,15 +5516,16 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5492 | 5516 | ||
| 5493 | p = XPROCESS (proc); | 5517 | p = XPROCESS (proc); |
| 5494 | 5518 | ||
| 5495 | #ifdef GNU_LINUX | 5519 | #ifndef WINDOWSNT |
| 5496 | /* getsockopt(,,SO_ERROR,,) is said to hang on some systems. | ||
| 5497 | So only use it on systems where it is known to work. */ | ||
| 5498 | { | 5520 | { |
| 5499 | socklen_t xlen = sizeof (xerrno); | 5521 | socklen_t xlen = sizeof (xerrno); |
| 5500 | if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen)) | 5522 | if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen)) |
| 5501 | xerrno = errno; | 5523 | xerrno = errno; |
| 5502 | } | 5524 | } |
| 5503 | #else | 5525 | #else |
| 5526 | /* On MS-Windows, getsockopt clears the error for the | ||
| 5527 | entire process, which may not be the right thing; see | ||
| 5528 | w32.c. Use getpeername instead. */ | ||
| 5504 | { | 5529 | { |
| 5505 | struct sockaddr pname; | 5530 | struct sockaddr pname; |
| 5506 | socklen_t pnamelen = sizeof (pname); | 5531 | socklen_t pnamelen = sizeof (pname); |
| @@ -5519,9 +5544,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5519 | #endif | 5544 | #endif |
| 5520 | if (xerrno) | 5545 | if (xerrno) |
| 5521 | { | 5546 | { |
| 5522 | p->tick = ++process_tick; | 5547 | Lisp_Object addrinfos |
| 5523 | pset_status (p, list2 (Qfailed, make_number (xerrno))); | 5548 | = connecting_status (p->status) ? XCDR (p->status) : Qnil; |
| 5549 | if (!NILP (addrinfos)) | ||
| 5550 | XSETCDR (p->status, XCDR (addrinfos)); | ||
| 5551 | else | ||
| 5552 | { | ||
| 5553 | p->tick = ++process_tick; | ||
| 5554 | pset_status (p, list2 (Qfailed, make_number (xerrno))); | ||
| 5555 | } | ||
| 5524 | deactivate_process (proc); | 5556 | deactivate_process (proc); |
| 5557 | if (!NILP (addrinfos)) | ||
| 5558 | connect_network_socket (proc, addrinfos, Qnil); | ||
| 5525 | } | 5559 | } |
| 5526 | else | 5560 | else |
| 5527 | { | 5561 | { |
| @@ -6998,7 +7032,7 @@ status_notify (struct Lisp_Process *deleting_process, | |||
| 6998 | 7032 | ||
| 6999 | /* If process is still active, read any output that remains. */ | 7033 | /* If process is still active, read any output that remains. */ |
| 7000 | while (! EQ (p->filter, Qt) | 7034 | while (! EQ (p->filter, Qt) |
| 7001 | && ! EQ (p->status, Qconnect) | 7035 | && ! connecting_status (p->status) |
| 7002 | && ! EQ (p->status, Qlisten) | 7036 | && ! EQ (p->status, Qlisten) |
| 7003 | /* Network or serial process not stopped: */ | 7037 | /* Network or serial process not stopped: */ |
| 7004 | && ! EQ (p->command, Qt) | 7038 | && ! EQ (p->command, Qt) |