aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2016-06-26 23:27:21 +0200
committerPaul Eggert2016-06-26 23:37:03 +0200
commit2989ad906048b374653d7030ebdaea62b670eed0 (patch)
treee05911945e6dad1249f2afea4cc6bbb6e03169f0 /src
parentd267aea2424783f5eefb6e733a6806ffd3323fa0 (diff)
downloademacs-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.c47
-rw-r--r--src/process.h4
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
538static bool
539connecting_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
4698wait_for_socket_fds (Lisp_Object process, char const *name) 4712wait_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)
4708static void 4722static void
4709wait_while_connecting (Lisp_Object process) 4723wait_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)