all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Paul Eggert <eggert@cs.ucla.edu>
To: 17976@debbugs.gnu.org
Cc: Juliusz Chroboczek <jch@pps.univ-paris-diderot.fr>,
	Andreas Schwab <schwab@suse.de>,
	23620@debbugs.gnu.org,
	Artur Malabarba <bruce.connor.am@gmail.com>,
	Lars Ingebrigtsen <larsi@gnus.org>
Subject: bug#23620: 24.3; url-retrieve-synchronously doesn't fallback to IPv4
Date: Sun, 26 Jun 2016 23:58:29 +0200	[thread overview]
Message-ID: <57705005.2060608@cs.ucla.edu> (raw)
In-Reply-To: <87oa7uou2t.fsf@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 579 bytes --]

No further comment on the proposed patch, and as it should be a win for 
non-WINDOWSNT I decided to install it on the Emacs master branch. I 
looked into how libcurl addresses the issue, and it doesn't care whether 
the errno value reported by getsockopt is ECONNREFUSED so I adjusted the 
Emacs patch accordingly (see attached) before installing. Please give it 
a try if you have the time.

This patch does not affect behavior if WINDOWSNT. If the bug does not 
occur on MS-Windows I hope we can close Bug#17976. Otherwise we should 
leave the bug open for the WINDOWSNT case.

[-- Attachment #2: 0001-Try-other-addresses-when-connecting-to-multihomed.patch --]
[-- Type: text/x-patch, Size: 6589 bytes --]

From 6a90b600323afc42ae3bd644d82ba7ea054a816a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 26 Jun 2016 23:27:21 +0200
Subject: [PATCH] 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).
---
 src/process.c | 47 +++++++++++++++++++++++++++++++++++------------
 src/process.h |  4 +++-
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/process.c b/src/process.c
index e669278..ed0c529 100644
--- a/src/process.c
+++ b/src/process.c
@@ -533,6 +533,14 @@ status_convert (int w)
     return Qrun;
 }
 
+/* True if STATUS is that of a process attempting connection.  */
+
+static bool
+connecting_status (Lisp_Object status)
+{
+  return CONSP (status) && EQ (XCAR (status), Qconnect);
+}
+
 /* Given a status-list, extract the three pieces of information
    and store them individually through the three pointers.  */
 
@@ -542,6 +550,9 @@ decode_status (Lisp_Object l, Lisp_Object *symbol, Lisp_Object *code,
 {
   Lisp_Object tem;
 
+  if (connecting_status (l))
+    l = XCAR (l);
+
   if (SYMBOLP (l))
     {
       *symbol = l;
@@ -3288,9 +3299,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
 	  eassert (FD_ISSET (s, &fdset));
 	  if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0)
 	    report_file_error ("Failed getsockopt", Qnil);
-	  if (xerrno)
+	  if (xerrno == 0)
+	    break;
+	  if (NILP (addrinfos))
 	    report_file_errno ("Failed connect", Qnil, xerrno);
-	  break;
 	}
 #endif /* !WINDOWSNT */
 
@@ -3399,7 +3411,9 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
       /* We may get here if connect did succeed immediately.  However,
 	 in that case, we still need to signal this like a non-blocking
 	 connection.  */
-      pset_status (p, Qconnect);
+      if (! (connecting_status (p->status)
+	     && EQ (XCDR (p->status), addrinfos)))
+	pset_status (p, Fcons (Qconnect, addrinfos));
       if (!FD_ISSET (inch, &connect_wait_mask))
 	{
 	  FD_SET (inch, &connect_wait_mask);
@@ -3960,7 +3974,7 @@ usage: (make-network-process &rest ARGS)  */)
   if (!p->is_server && NILP (addrinfos))
     {
       p->dns_request = dns_request;
-      p->status = Qconnect;
+      p->status = list1 (Qconnect);
       return proc;
     }
 #endif
@@ -4673,7 +4687,7 @@ check_for_dns (Lisp_Object proc)
       addrinfos = Fnreverse (addrinfos);
     }
   /* The DNS lookup failed. */
-  else if (EQ (p->status, Qconnect))
+  else if (connecting_status (p->status))
     {
       deactivate_process (proc);
       pset_status (p, (list2
@@ -4686,7 +4700,7 @@ check_for_dns (Lisp_Object proc)
   free_dns_request (proc);
 
   /* This process should not already be connected (or killed). */
-  if (!EQ (p->status, Qconnect))
+  if (! connecting_status (p->status))
     return Qnil;
 
   return addrinfos;
@@ -4698,7 +4712,7 @@ static void
 wait_for_socket_fds (Lisp_Object process, char const *name)
 {
   while (XPROCESS (process)->infd < 0
-	 && EQ (XPROCESS (process)->status, Qconnect))
+	 && connecting_status (XPROCESS (process)->status))
     {
       add_to_log ("Waiting for socket from %s...", build_string (name));
       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)
 static void
 wait_while_connecting (Lisp_Object process)
 {
-  while (EQ (XPROCESS (process)->status, Qconnect))
+  while (connecting_status (XPROCESS (process)->status))
     {
       add_to_log ("Waiting for connection...");
       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,
 	update_status (wait_proc);
       if (wait_proc
 	  && ! EQ (wait_proc->status, Qrun)
-	  && ! EQ (wait_proc->status, Qconnect))
+	  && ! connecting_status (wait_proc->status))
 	{
 	  bool read_some_bytes = false;
 
@@ -5520,9 +5534,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 #endif
 	      if (xerrno)
 		{
-		  p->tick = ++process_tick;
-		  pset_status (p, list2 (Qfailed, make_number (xerrno)));
+		  Lisp_Object addrinfos
+		    = connecting_status (p->status) ? XCDR (p->status) : Qnil;
+		  if (!NILP (addrinfos))
+		    XSETCDR (p->status, XCDR (addrinfos));
+		  else
+		    {
+		      p->tick = ++process_tick;
+		      pset_status (p, list2 (Qfailed, make_number (xerrno)));
+		    }
 		  deactivate_process (proc);
+		  if (!NILP (addrinfos))
+		    connect_network_socket (proc, addrinfos, Qnil);
 		}
 	      else
 		{
@@ -6999,7 +7022,7 @@ status_notify (struct Lisp_Process *deleting_process,
 
 	  /* If process is still active, read any output that remains.  */
 	  while (! EQ (p->filter, Qt)
-		 && ! EQ (p->status, Qconnect)
+		 && ! connecting_status (p->status)
 		 && ! EQ (p->status, Qlisten)
 		 /* Network or serial process not stopped:  */
 		 && ! EQ (p->command, Qt)
diff --git a/src/process.h b/src/process.h
index 4430377..6c227bc 100644
--- a/src/process.h
+++ b/src/process.h
@@ -83,7 +83,9 @@ struct Lisp_Process
     Lisp_Object mark;
 
     /* Symbol indicating status of process.
-       This may be a symbol: run, open, closed, listen, connect, or failed.
+       This may be a symbol: run, open, closed, listen, or failed.
+       Or it may be a pair (connect . ADDRINFOS) where ADDRINFOS is
+       a list of remaining (PROTOCOL . ADDRINFO) pairs to try.
        Or it may be (failed ERR) where ERR is an integer, string or symbol.
        Or it may be a list, whose car is stop, exit or signal
        and whose cdr is a pair (EXIT_CODE . COREDUMP_FLAG)
-- 
2.5.5


  parent reply	other threads:[~2016-06-26 21:58 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-25 18:45 bug#23620: 25.0.94; url-retrieve fails on localhost Artur Malabarba
2016-05-28 16:42 ` Paul Eggert
2016-06-01 14:55   ` Artur Malabarba
2016-06-01 16:43     ` Paul Eggert
2016-06-01 19:04       ` Artur Malabarba
2016-06-26 21:58 ` Paul Eggert [this message]
2016-06-26 23:20   ` bug#23620: 24.3; url-retrieve-synchronously doesn't fallback to IPv4 Juliusz Chroboczek
2017-10-21 23:55     ` bug#17976: " Noam Postavsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=57705005.2060608@cs.ucla.edu \
    --to=eggert@cs.ucla.edu \
    --cc=17976@debbugs.gnu.org \
    --cc=23620@debbugs.gnu.org \
    --cc=bruce.connor.am@gmail.com \
    --cc=jch@pps.univ-paris-diderot.fr \
    --cc=larsi@gnus.org \
    --cc=schwab@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.