From b37f049826d5712e88b660832e6ef7a7e4bd5f7d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Thu, 22 Nov 2001 13:06:41 +0100
Subject: [PATCH] Several fixes pertaining to Stdio.File()->async_connect().
 Fixes [bug 2403]. Added some support for having close callbacks without read
 callbacks.

Rev: lib/modules/Stdio.pmod/module.pmod:1.127
---
 lib/modules/Stdio.pmod/module.pmod | 104 ++++++++++++++++++++++-------
 1 file changed, 80 insertions(+), 24 deletions(-)

diff --git a/lib/modules/Stdio.pmod/module.pmod b/lib/modules/Stdio.pmod/module.pmod
index 43ae5c0a06..46a263c84c 100644
--- a/lib/modules/Stdio.pmod/module.pmod
+++ b/lib/modules/Stdio.pmod/module.pmod
@@ -1,4 +1,4 @@
-// $Id: module.pmod,v 1.126 2001/10/28 17:58:57 nilsson Exp $
+// $Id: module.pmod,v 1.127 2001/11/22 12:06:41 grubba Exp $
 #pike __REAL_VERSION__
 
 
@@ -305,27 +305,25 @@ class File
 
   static private function(int, mixed ...:void) _async_cb;
   static private array(mixed) _async_args;
-  static private void _async_connected(mixed|void ignored)
+  static private void _async_check_cb(mixed|void ignored)
   {
     // Copy the args to avoid races.
-    if(!_async_cb) return;
     function(int, mixed ...:void) cb = _async_cb;
     array(mixed) args = _async_args;
     _async_cb = 0;
     _async_args = 0;
     set_nonblocking(0,0,0);
-    cb(1, @args);
-  }
-  static private void _async_failed(mixed|void ignored)
-  {
-    // Copy the args to avoid races.
-    if(!_async_cb) return;
-    function(int, mixed ...:void) cb = _async_cb;
-    array(mixed) args = _async_args;
-    _async_cb = 0;
-    _async_args = 0;
-    set_nonblocking(0,0,0);
-    cb(0, @args);
+    if (cb) {
+      if (_fd && query_address()) {
+	// Connection OK.
+	cb(1, @args);
+      } else {
+	// Connection failed.
+	// Make sure the state is reset.
+	close();
+	cb(0, @args);
+      }
+    }
   }
 
   function(:string) read_function(int nbytes)
@@ -358,21 +356,21 @@ class File
 		    function(int, mixed ...:void) callback,
 		    mixed ... args)
   {
-    if (!_fd && !open_socket()) {
+    if (!(_fd || query_address()) && !open_socket()) {
       // Out of sockets?
       return 0;
     }
     _async_cb = callback;
     _async_args = args;
-    set_nonblocking(0, _async_connected, _async_failed, _async_failed, 0);
+    set_nonblocking(0, _async_check_cb, _async_check_cb, _async_check_cb, 0);
     mixed err;
     int res;
     if (err = catch(res = connect(host, port))) {
       // Illegal format. -- Bad hostname?
-      call_out(_async_failed, 0);
+      call_out(_async_check_cb, 0);
     } else if (!res) {
       // Connect failed.
-      call_out(_async_failed, 0);
+      call_out(_async_check_cb, 0);
     }
     return(1);	// OK so far. (Or rather the callback will be used).
   }
@@ -517,7 +515,9 @@ class File
       if(___write_callback = _o->___write_callback)
 	_fd->_write_callback=__stdio_write_callback;
 
-      ___close_callback = _o->___close_callback;
+      if ((___close_callback = _o->___close_callback) && (!___read_callback) {
+	_fd->_read_callback = __stdio_close_callback;
+      }
 #if constant(files.__HAVE_OOB__)
       if(___read_oob_callback = _o->___read_oob_callback)
 	_fd->_read_oob_callback = __stdio_read_oob_callback;
@@ -544,13 +544,17 @@ class File
     File to = File();
     to->is_file = is_file;
     to->_fd = _fd;
+
+    // FIXME: This looks broken... Isn't __stdio_*_callback declared static?
     if(to->___read_callback = ___read_callback)
       _fd->_read_callback=to->__stdio_read_callback;
 
     if(to->___write_callback = ___write_callback)
       _fd->_write_callback=to->__stdio_write_callback;
 
-    to->___close_callback = ___close_callback;
+    if ((to->___close_callback = ___close_callback) && (!___read_callback)) {
+      _fd->_read_callback = to->__stdio_close_callback;
+    }
 #if constant(files.__HAVE_OOB__)
     if(to->___read_oob_callback = ___read_oob_callback)
       _fd->_read_oob_callback=to->__stdio_read_oob_callback;
@@ -673,6 +677,35 @@ class File
     }
   }
 
+  static void __stdio_close_callback()
+  {
+    string s=::read(0, 1);
+    if(!s)
+    {
+      switch(errno())
+      {
+#if constant(system.EINTR)
+         case system.EINTR:
+#endif
+
+#if constant(system.EWOULDBLOCK)
+	 case system.EWOULDBLOCK:
+#endif
+	   ::set_read_callback(__stdio_close_callback);
+           return;
+      }
+    } else {
+      // There's data to read...
+      ::set_read_callback(0);
+      ___close_callback = 0;
+      return;
+    }
+    ::set_read_callback(0);
+    if (___close_callback) {
+      ___close_callback(___id);
+    }
+  }
+
   static void __stdio_write_callback() { ___write_callback(___id); }
 
 #if constant(files.__HAVE_OOB__)
@@ -732,7 +765,18 @@ class File
   //! @[set_nonblocking()], @[set_read_callback]
 
   //! @ignore
-  CBFUNC(read_callback)
+  void set_read_callback(mixed read_cb)
+  {
+    CHECK_OPEN();
+    ::set_read_callback(((___read_callback = read_cb) &&
+			 __stdio_read_callback) ||
+			(___close_callback && __stdio_close_callback));
+  }
+
+  mixed query_read_callback()
+  {
+    return ___read_callback;
+  }
   //! @endignore
 
   //! @decl void set_write_callback(function(mixed:void) write_cb)
@@ -803,7 +847,17 @@ class File
   //! @[query_close_callback()], @[set_read_callback()],
   //! @[set_write_callback()]
   //!
-  void set_close_callback(mixed c)  { ___close_callback=c; }
+  void set_close_callback(mixed c)  {
+    CHECK_OPEN();
+    ___close_callback=c;
+    if (!___read_callback) {
+      if (c) {
+	::set_read_callback(__stdio_close_callback);
+      } else {
+	::set_read_callback(0);
+      }
+    }
+  }
 
   //! @decl function(mixed:void) query_close_callback()
   //!
@@ -882,7 +936,9 @@ class File
 
     _SET(read_callback,rcb);
     _SET(write_callback,wcb);
-    ___close_callback=ccb;
+    if ((___close_callback = ccb) && (!rcb)) {
+      ::set_read_callback(__stdio_close_callback);
+    }
 
 #if constant(files.__HAVE_OOB__)
     _SET(read_oob_callback,roobcb);
-- 
GitLab