changeset 107544:afbf4ad814c7

Call `select' for interrupted `connect' rather than creating new socket (Bug#5173).
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Thu, 25 Mar 2010 17:48:52 +0900
parents c56cc351f300
children 805495d3c451
files src/ChangeLog src/process.c
diffstat 2 files changed, 37 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Wed Mar 24 23:18:17 2010 -0700
+++ b/src/ChangeLog	Thu Mar 25 17:48:52 2010 +0900
@@ -1,3 +1,8 @@
+2010-03-25  Helmut Eller  <eller.helmut@gmail.com>
+
+	* process.c (Fmake_network_process): Call `select' for interrupted
+	`connect' rather than creating new socket (Bug#5173).
+
 2010-03-24  Jan Djärv  <jan.h.d@swipnet.se>
 
 	* frame.c (x_get_arg): Handle RES_TYPE_BOOLEAN_NUMBER (bug #5736).
--- a/src/process.c	Wed Mar 24 23:18:17 2010 -0700
+++ b/src/process.c	Thu Mar 25 17:48:52 2010 +0900
@@ -3534,8 +3534,6 @@
     {
       int optn, optbits;
 
-    retry_connect:
-
       s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol);
       if (s < 0)
 	{
@@ -3652,6 +3650,38 @@
 #endif
 #endif
 #endif
+      if (xerrno == EINTR)
+	{
+	  /* Unlike most other syscalls connect() cannot be called
+	     again.  (That would return EALREADY.)  The proper way to
+	     wait for completion is select(). */
+	  int sc;
+	  SELECT_TYPE fdset;
+	retry_select:
+	  FD_ZERO (&fdset);
+	  FD_SET (s, &fdset);
+	  QUIT;
+	  sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
+		       (EMACS_TIME *)0);
+	  if (sc == -1)
+	    {
+	      if (errno == EINTR) 
+		goto retry_select;
+	      else 
+		report_file_error ("select failed", Qnil);
+	    }
+	  eassert (sc > 0);
+	  {
+	    int len = sizeof xerrno;
+	    eassert (FD_ISSET (s, &fdset));
+	    if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1)
+	      report_file_error ("getsockopt failed", Qnil);
+	    if (xerrno != 0)
+	      errno = xerrno, report_file_error ("error during connect", Qnil);
+	    else
+	      break;
+	  }
+	}
 
       immediate_quit = 0;
 
@@ -3659,9 +3689,6 @@
       specpdl_ptr = specpdl + count1;
       emacs_close (s);
       s = -1;
-
-      if (xerrno == EINTR)
-	goto retry_connect;
     }
 
   if (s >= 0)