diff options
| author | Paul Eggert | 2016-06-26 23:27:21 +0200 |
|---|---|---|
| committer | Paul Eggert | 2016-06-26 23:37:03 +0200 |
| commit | 2989ad906048b374653d7030ebdaea62b670eed0 (patch) | |
| tree | e05911945e6dad1249f2afea4cc6bbb6e03169f0 /src | |
| parent | d267aea2424783f5eefb6e733a6806ffd3323fa0 (diff) | |
| download | emacs-2989ad906048b374653d7030ebdaea62b670eed0.tar.gz emacs-2989ad906048b374653d7030ebdaea62b670eed0.zip | |
Try other addresses when connecting to multihomed
Problem reported by Juliusz Chroboczek (Bug#17976)
and by Artur Malabarba (Bug#23620).
Patch from a suggestion by Andreas Schwab in:
http://bugs.gnu.org/17976#39
This patch is for non-MS-Windows platforms.
I don't know the situation on MS-Windows.
* src/process.c (connecting_status):
New function, for (connect . ADDRINFOS).
(connect_network_socket, check_for_dns, wait_for_socket_fds)
(wait_while_connecting, wait_reading_process_output, status_notify):
Use it.
(decode_status, Fmake_network_process):
Support (connect . ADDRINFOS) status.
(connect_network_socket) [!WINDOWSNT]:
If the connection failed and there are other addresses to try, do not
signal an error; instead, loop around to try the next address.
(wait_reading_process_output): Advance to the next address
if there are multiple addresses and the first remaining address
failed.
* src/process.h (struct Lisp_Process.status): Adjust comment
to describe (connect . ADDRINFOS).
Diffstat (limited to 'src')
| -rw-r--r-- | src/process.c | 47 | ||||
| -rw-r--r-- | src/process.h | 4 |
2 files changed, 38 insertions, 13 deletions
diff --git a/src/process.c b/src/process.c index e669278f6e3..ed0c529cd75 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -533,6 +533,14 @@ 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 | ||
| @@ -542,6 +550,9 @@ decode_status (Lisp_Object l, Lisp_Object *symbol, Lisp_Object *code, | |||
| 542 | { | 550 | { |
| 543 | Lisp_Object tem; | 551 | Lisp_Object tem; |
| 544 | 552 | ||
| 553 | if (connecting_status (l)) | ||
| 554 | l = XCAR (l); | ||
| 555 | |||
| 545 | if (SYMBOLP (l)) | 556 | if (SYMBOLP (l)) |
| 546 | { | 557 | { |
| 547 | *symbol = l; | 558 | *symbol = l; |
| @@ -3288,9 +3299,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3288 | eassert (FD_ISSET (s, &fdset)); | 3299 | eassert (FD_ISSET (s, &fdset)); |
| 3289 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) | 3300 | if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0) |
| 3290 | report_file_error ("Failed getsockopt", Qnil); | 3301 | report_file_error ("Failed getsockopt", Qnil); |
| 3291 | if (xerrno) | 3302 | if (xerrno == 0) |
| 3303 | break; | ||
| 3304 | if (NILP (addrinfos)) | ||
| 3292 | report_file_errno ("Failed connect", Qnil, xerrno); | 3305 | report_file_errno ("Failed connect", Qnil, xerrno); |
| 3293 | break; | ||
| 3294 | } | 3306 | } |
| 3295 | #endif /* !WINDOWSNT */ | 3307 | #endif /* !WINDOWSNT */ |
| 3296 | 3308 | ||
| @@ -3399,7 +3411,9 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, | |||
| 3399 | /* We may get here if connect did succeed immediately. However, | 3411 | /* We may get here if connect did succeed immediately. However, |
| 3400 | in that case, we still need to signal this like a non-blocking | 3412 | in that case, we still need to signal this like a non-blocking |
| 3401 | connection. */ | 3413 | connection. */ |
| 3402 | pset_status (p, Qconnect); | 3414 | if (! (connecting_status (p->status) |
| 3415 | && EQ (XCDR (p->status), addrinfos))) | ||
| 3416 | pset_status (p, Fcons (Qconnect, addrinfos)); | ||
| 3403 | if (!FD_ISSET (inch, &connect_wait_mask)) | 3417 | if (!FD_ISSET (inch, &connect_wait_mask)) |
| 3404 | { | 3418 | { |
| 3405 | FD_SET (inch, &connect_wait_mask); | 3419 | FD_SET (inch, &connect_wait_mask); |
| @@ -3960,7 +3974,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3960 | if (!p->is_server && NILP (addrinfos)) | 3974 | if (!p->is_server && NILP (addrinfos)) |
| 3961 | { | 3975 | { |
| 3962 | p->dns_request = dns_request; | 3976 | p->dns_request = dns_request; |
| 3963 | p->status = Qconnect; | 3977 | p->status = list1 (Qconnect); |
| 3964 | return proc; | 3978 | return proc; |
| 3965 | } | 3979 | } |
| 3966 | #endif | 3980 | #endif |
| @@ -4673,7 +4687,7 @@ check_for_dns (Lisp_Object proc) | |||
| 4673 | addrinfos = Fnreverse (addrinfos); | 4687 | addrinfos = Fnreverse (addrinfos); |
| 4674 | } | 4688 | } |
| 4675 | /* The DNS lookup failed. */ | 4689 | /* The DNS lookup failed. */ |
| 4676 | else if (EQ (p->status, Qconnect)) | 4690 | else if (connecting_status (p->status)) |
| 4677 | { | 4691 | { |
| 4678 | deactivate_process (proc); | 4692 | deactivate_process (proc); |
| 4679 | pset_status (p, (list2 | 4693 | pset_status (p, (list2 |
| @@ -4686,7 +4700,7 @@ check_for_dns (Lisp_Object proc) | |||
| 4686 | free_dns_request (proc); | 4700 | free_dns_request (proc); |
| 4687 | 4701 | ||
| 4688 | /* This process should not already be connected (or killed). */ | 4702 | /* This process should not already be connected (or killed). */ |
| 4689 | if (!EQ (p->status, Qconnect)) | 4703 | if (! connecting_status (p->status)) |
| 4690 | return Qnil; | 4704 | return Qnil; |
| 4691 | 4705 | ||
| 4692 | return addrinfos; | 4706 | return addrinfos; |
| @@ -4698,7 +4712,7 @@ static void | |||
| 4698 | wait_for_socket_fds (Lisp_Object process, char const *name) | 4712 | wait_for_socket_fds (Lisp_Object process, char const *name) |
| 4699 | { | 4713 | { |
| 4700 | while (XPROCESS (process)->infd < 0 | 4714 | while (XPROCESS (process)->infd < 0 |
| 4701 | && EQ (XPROCESS (process)->status, Qconnect)) | 4715 | && connecting_status (XPROCESS (process)->status)) |
| 4702 | { | 4716 | { |
| 4703 | add_to_log ("Waiting for socket from %s...", build_string (name)); | 4717 | 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); | 4718 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); |
| @@ -4708,7 +4722,7 @@ wait_for_socket_fds (Lisp_Object process, char const *name) | |||
| 4708 | static void | 4722 | static void |
| 4709 | wait_while_connecting (Lisp_Object process) | 4723 | wait_while_connecting (Lisp_Object process) |
| 4710 | { | 4724 | { |
| 4711 | while (EQ (XPROCESS (process)->status, Qconnect)) | 4725 | while (connecting_status (XPROCESS (process)->status)) |
| 4712 | { | 4726 | { |
| 4713 | add_to_log ("Waiting for connection..."); | 4727 | add_to_log ("Waiting for connection..."); |
| 4714 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); | 4728 | wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0); |
| @@ -5010,7 +5024,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5010 | update_status (wait_proc); | 5024 | update_status (wait_proc); |
| 5011 | if (wait_proc | 5025 | if (wait_proc |
| 5012 | && ! EQ (wait_proc->status, Qrun) | 5026 | && ! EQ (wait_proc->status, Qrun) |
| 5013 | && ! EQ (wait_proc->status, Qconnect)) | 5027 | && ! connecting_status (wait_proc->status)) |
| 5014 | { | 5028 | { |
| 5015 | bool read_some_bytes = false; | 5029 | bool read_some_bytes = false; |
| 5016 | 5030 | ||
| @@ -5520,9 +5534,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 5520 | #endif | 5534 | #endif |
| 5521 | if (xerrno) | 5535 | if (xerrno) |
| 5522 | { | 5536 | { |
| 5523 | p->tick = ++process_tick; | 5537 | Lisp_Object addrinfos |
| 5524 | pset_status (p, list2 (Qfailed, make_number (xerrno))); | 5538 | = connecting_status (p->status) ? XCDR (p->status) : Qnil; |
| 5539 | if (!NILP (addrinfos)) | ||
| 5540 | XSETCDR (p->status, XCDR (addrinfos)); | ||
| 5541 | else | ||
| 5542 | { | ||
| 5543 | p->tick = ++process_tick; | ||
| 5544 | pset_status (p, list2 (Qfailed, make_number (xerrno))); | ||
| 5545 | } | ||
| 5525 | deactivate_process (proc); | 5546 | deactivate_process (proc); |
| 5547 | if (!NILP (addrinfos)) | ||
| 5548 | connect_network_socket (proc, addrinfos, Qnil); | ||
| 5526 | } | 5549 | } |
| 5527 | else | 5550 | else |
| 5528 | { | 5551 | { |
| @@ -6999,7 +7022,7 @@ status_notify (struct Lisp_Process *deleting_process, | |||
| 6999 | 7022 | ||
| 7000 | /* If process is still active, read any output that remains. */ | 7023 | /* If process is still active, read any output that remains. */ |
| 7001 | while (! EQ (p->filter, Qt) | 7024 | while (! EQ (p->filter, Qt) |
| 7002 | && ! EQ (p->status, Qconnect) | 7025 | && ! connecting_status (p->status) |
| 7003 | && ! EQ (p->status, Qlisten) | 7026 | && ! EQ (p->status, Qlisten) |
| 7004 | /* Network or serial process not stopped: */ | 7027 | /* Network or serial process not stopped: */ |
| 7005 | && ! EQ (p->command, Qt) | 7028 | && ! EQ (p->command, Qt) |
diff --git a/src/process.h b/src/process.h index 4430377877a..6c227bc2266 100644 --- a/src/process.h +++ b/src/process.h | |||
| @@ -83,7 +83,9 @@ struct Lisp_Process | |||
| 83 | Lisp_Object mark; | 83 | Lisp_Object mark; |
| 84 | 84 | ||
| 85 | /* Symbol indicating status of process. | 85 | /* Symbol indicating status of process. |
| 86 | This may be a symbol: run, open, closed, listen, connect, or failed. | 86 | This may be a symbol: run, open, closed, listen, or failed. |
| 87 | Or it may be a pair (connect . ADDRINFOS) where ADDRINFOS is | ||
| 88 | a list of remaining (PROTOCOL . ADDRINFO) pairs to try. | ||
| 87 | Or it may be (failed ERR) where ERR is an integer, string or symbol. | 89 | Or it may be (failed ERR) where ERR is an integer, string or symbol. |
| 88 | Or it may be a list, whose car is stop, exit or signal | 90 | Or it may be a list, whose car is stop, exit or signal |
| 89 | and whose cdr is a pair (EXIT_CODE . COREDUMP_FLAG) | 91 | and whose cdr is a pair (EXIT_CODE . COREDUMP_FLAG) |