aboutsummaryrefslogtreecommitdiffstats
path: root/src/process.c
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/process.c
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/process.c')
-rw-r--r--src/process.c47
1 files changed, 35 insertions, 12 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)