diff --git a/lib/modules/Remote.pmod/connection.pike b/lib/modules/Remote.pmod/connection.pike
index 124ff6630a63aa43264d457675a3f7ac9599ea57..0f9843b1f23409c9d7e3ac9ed7cba934b9b2cc61 100644
--- a/lib/modules/Remote.pmod/connection.pike
+++ b/lib/modules/Remote.pmod/connection.pike
@@ -109,9 +109,8 @@ void close()
 {
   want_close = 1;
   if (!(reading || sizeof (write_buffer))) {
-    con->set_blocking();
-    con->close();
-    closed_connection();
+    if (!catch {con->set_blocking(); con->close();})
+      closed_connection();
   }
   else
     DEBUGMSG("close delayed\n");
@@ -149,11 +148,9 @@ void write_some(int|void ignore)
     write_buffer = write_buffer[c..];
     DEBUGMSG("wrote "+c+" bytes\n");
   }
-  if (want_close && !(reading || sizeof(write_buffer))) {
-    con->set_blocking();
-    con->close();
-    closed_connection();
-  }
+  if (want_close && !(reading || sizeof(write_buffer)))
+    if (!catch {con->set_blocking(); con->close();})
+      closed_connection();
 }
 
 void send(string s)
@@ -242,9 +239,9 @@ void read_some(int ignore, string s)
   if (request_size && sizeof(read_buffer) >= request_size && !want_close)
   {
     array data = decode_value(read_buffer[0..request_size-1]);
+    DEBUGMSG("got " + request_size + " bytes of message: "+ctx->describe(data)+"\n");
     read_buffer = read_buffer[request_size..];
     request_size = 0;
-    DEBUGMSG("got message: "+ctx->describe(data)+"\n");
     reading = 1;
     switch(data[0]) {
 
@@ -294,6 +291,10 @@ void read_some(int ignore, string s)
   }
 }
 
+#if constant(Thread.Mutex)
+object(Thread.Mutex) block_read_mutex = Thread.Mutex();
+#endif
+
 
 // - call_sync
 //
@@ -312,17 +313,31 @@ mixed call_sync(array data)
   send(sprintf("%4c%s", sizeof(s), s));
   while(zero_type(finished_calls[refno]))
   {
-    string s = con->read(8192,1);
-    if(!s || !strlen(s))
-    {
-      con->close();
-      closed_connection();
-      if (!nice)
-	 error("Could not read");
+#if constant(Thread.Mutex)
+    // Only one thread does read(), the rest just waits. When the
+    // read() finishes, all threads loop once.
+    object lock = block_read_mutex->trylock();
+    if (lock) {
+#endif
+      string s = con->read(8192,1);
+      if(s && strlen(s)) read_some(0,s);
       else
-	 return ([])[0]; // failed, like
+      {
+#if constant(Thread.Mutex)
+	lock = 0;
+#endif
+	if (!catch (con->close()))
+	  closed_connection();
+	if (!nice)
+	  error("Could not read");
+	else
+	  return ([])[0]; // failed, like
+      }
+#if constant(Thread.Mutex)
+      lock = 0;
     }
-    read_some(0,s);
+    else block_read_mutex->lock();
+#endif
   }
   con->set_nonblocking(read_some, write_some, closed_connection);
   return get_result(refno);