diff --git a/lib/modules/Sql.pmod/pgsql.pike b/lib/modules/Sql.pmod/pgsql.pike
index dce5a04358fcdb9dbe9c24b7cc95653c64c15adc..5416c1f250c7d10e85b4d56875d9b2740178b3ce 100644
--- a/lib/modules/Sql.pmod/pgsql.pike
+++ b/lib/modules/Sql.pmod/pgsql.pike
@@ -878,6 +878,74 @@ private inline void throwdelayederror(object parent) {
   .pgsql_util.throwdelayederror(parent);
 }
 
+private void startquery(int forcetext, .pgsql_util.sql_result portal, string q,
+ mapping(string:mixed) tp, string preparedname) {
+  .pgsql_util.conxion c = proxy.c;
+  if (forcetext) {	// FIXME What happens if portals are still open?
+    portal._unnamedportalkey = proxy.unnamedportalmux->lock(1);
+    portal._portalname = "";
+    portal->_parseportal(); portal->_bindportal();
+    proxy.readyforquerycount++;
+    {
+      Thread.MutexKey lock = proxy.unnamedstatement->lock(1);
+      .pgsql_util.conxsess cs = c->start(1);
+      CHAIN(cs)->add_int8('Q')->add_hstring(({q, 0}), 4, 4);
+      cs->sendcmd(FLUSHLOGSEND, portal);
+    }
+    PD("Simple query: %O\n", q);
+  } else {
+    object plugbuffer;
+    portal->_parseportal();
+    if (!sizeof(preparedname) || !tp || !tp.preparedname) {
+      if (!sizeof(preparedname))
+        preparedname =
+          (portal._unnamedstatementkey = proxy.unnamedstatement->trylock(1))
+           ? "" : PTSTMTPREFIX + int2hex(ptstmtcount++);
+      PD("Parse statement %O=%O\n", preparedname, q);
+      plugbuffer = c->start();
+      CHAIN(plugbuffer)->add_int8('P')
+       ->add_hstring(({preparedname, 0, q, "\0\0\0"}), 4, 4)
+#if 0
+      // Even though the protocol doesn't require the Parse command to be
+      // followed by a flush, it makes a VERY noticeable difference in
+      // performance if it is omitted; seems like a flaw in the PostgreSQL
+      // server v8.3.3
+      // In v8.4 and later, things speed up slightly when it is omitted.
+      ->add(PGFLUSH)
+#endif
+      ;
+    } else {				// Use the name from the cache
+      preparedname = tp.preparedname;	// to shortcut a potential race
+      PD("Using prepared statement %s for %O\n", preparedname, q);
+    }
+    portal._preparedname = preparedname;
+    if (!tp || !tp.datatypeoid) {
+      PD("Describe statement %O\n", preparedname);
+      if (!plugbuffer)
+        plugbuffer = c->start();
+      CHAIN(plugbuffer)->add_int8('D')
+       ->add_hstring(({'S', preparedname, 0}), 4, 4);
+      plugbuffer->sendcmd(FLUSHSEND, portal);
+    } else {
+      if (plugbuffer)
+        plugbuffer->sendcmd(KEEP);
+#ifdef PG_STATS
+      skippeddescribe++;
+#endif
+      portal->_setrowdesc(tp.datarowdesc, tp.datarowtypes);
+    }
+    if ((portal._tprepared=tp) && tp.datatypeoid) {
+      mixed e = catch(portal->_preparebind(tp.datatypeoid));
+      if (e && !portal.delayederror) {
+        portal._unnamedstatementkey = 0;	// Release early, release often
+        throw(e);
+      }
+    }
+    if (!proxy.unnamedstatement)
+      portal._unnamedstatementkey = 0;		// Cover for a destruct race
+  }
+}
+
 //! This is the only provided direct interface which allows you to query the
 //! database.  A simpler synchronous interface can be used through @[query()].
 //!
@@ -1011,7 +1079,6 @@ private inline void throwdelayederror(object parent) {
   if (has_value(q, "\0"))
     ERROR("Querystring %O contains invalid literal nul-characters\n", q);
   mapping(string:mixed) tp;
-  int tstart;
   /*
    * FIXME What happens with regards to this detection when presented with
    *       multistatement text-queries?
@@ -1031,8 +1098,7 @@ private inline void throwdelayederror(object parent) {
         prepstmtused++;
 #endif
         preparedname = tp.preparedname;
-      } else if((tstart = tp.trun)
-              && tp.tparse*FACTORPLAN >= tstart
+      } else if(tp.trun && tp.tparse*FACTORPLAN >= tp.trun
               && (undefinedp(options.cache_autoprepared_statements)
              || options.cache_autoprepared_statements))
         preparedname = PREPSTMTPREFIX + int2hex(pstmtcount++);
@@ -1061,11 +1127,10 @@ private inline void throwdelayederror(object parent) {
       }
     }
     if (sizeof(CHAIN(plugbuffer))) {
-      PD("%O\n",(string)CHAIN(plugbuffer));
+      PD("%O\n", (string)CHAIN(plugbuffer));
       plugbuffer->sendcmd(FLUSHSEND);			      // close expireds
     } else
       plugbuffer->sendcmd(KEEP);			       // close start()
-    tstart = gethrtime();
   } else				  // sql_result autoassigns to portal
     tp = 0;
   .pgsql_util.sql_result portal;
@@ -1076,69 +1141,11 @@ private inline void throwdelayederror(object parent) {
   portalsopened++;
 #endif
   proxy.clearmessage = 1;
-  if (forcetext) {	// FIXME What happens if portals are still open?
-    portal._unnamedportalkey = proxy.unnamedportalmux->lock(1);
-    portal._portalname = "";
-    portal->_parseportal(); portal->_bindportal();
-    proxy.readyforquerycount++;
-    {
-      Thread.MutexKey lock = proxy.unnamedstatement->lock(1);
-      .pgsql_util.conxsess cs = c->start(1);
-      CHAIN(cs)->add_int8('Q')->add_hstring(({q, 0}), 4, 4);
-      cs->sendcmd(FLUSHLOGSEND, portal);
-    }
-    PD("Simple query: %O\n", q);
-  } else {
-    object plugbuffer;
-    portal->_parseportal();
-    if (!sizeof(preparedname) || !tp || !tp.preparedname) {
-      if (!sizeof(preparedname))
-        preparedname=
-          (portal._unnamedstatementkey = proxy.unnamedstatement->trylock(1))
-           ? "" : PTSTMTPREFIX+int2hex(ptstmtcount++);
-      PD("Parse statement %O=%O\n", preparedname, q);
-      plugbuffer = c->start();
-      CHAIN(plugbuffer)->add_int8('P')
-       ->add_hstring(({preparedname, 0, q, "\0\0\0"}), 4, 4)
-#if 0
-      // Even though the protocol doesn't require the Parse command to be
-      // followed by a flush, it makes a VERY noticeable difference in
-      // performance if it is omitted; seems like a flaw in the PostgreSQL
-      // server v8.3.3
-      // In v8.4 and later, things speed up slightly when it is omitted.
-      ->add(PGFLUSH)
-#endif
-      ;
-    } else {				// Use the name from the cache
-      preparedname = tp.preparedname;	// to shortcut a potential race
-      PD("Using prepared statement %s for %O\n", preparedname, q);
-    }
-    portal._preparedname = preparedname;
-    if (!tp || !tp.datatypeoid) {
-      PD("Describe statement %O\n", preparedname);
-      if (!plugbuffer)
-        plugbuffer = c->start();
-      CHAIN(plugbuffer)->add_int8('D')
-       ->add_hstring(({'S', preparedname, 0}), 4, 4);
-      plugbuffer->sendcmd(FLUSHSEND, portal);
-    } else {
-      if (plugbuffer)
-        plugbuffer->sendcmd(KEEP);
-#ifdef PG_STATS
-      skippeddescribe++;
-#endif
-      portal->_setrowdesc(tp.datarowdesc, tp.datarowtypes);
-    }
-    if ((portal._tprepared=tp) && tp.datatypeoid) {
-      mixed e = catch(portal->_preparebind(tp.datatypeoid));
-      if (e && !portal.delayederror) {
-        portal._unnamedstatementkey = 0;	// Release early, release often
-        throw(e);
-      }
-    }
-    if (!proxy.unnamedstatement)
-      portal._unnamedstatementkey = 0;		// Cover for a destruct race
-  }
+  // Do not run a query in the local_backend to prevent deadlocks
+  if (Thread.this_thread() == .pgsql_util.local_backend.executing_thread())
+    call_out(startquery, 0, forcetext, portal, q, tp, preparedname);
+  else
+    startquery(forcetext, portal, q, tp, preparedname);
   throwdelayederror(portal);
   return portal;
 }
diff --git a/lib/modules/Sql.pmod/pgsql_util.pmod b/lib/modules/Sql.pmod/pgsql_util.pmod
index dd12ab5e8cde98ee659c9b8f04b34e2468c7fda3..815ca3e6595cb180d0e56ff6df42965a8f2a6a8c 100644
--- a/lib/modules/Sql.pmod/pgsql_util.pmod
+++ b/lib/modules/Sql.pmod/pgsql_util.pmod
@@ -126,7 +126,7 @@ private void run_local_backend() {
        || sizeof(local_backend->call_out_info())) {
         mixed err;
         if (err = catch(local_backend(4096.0)))
-          werror(describe_backtrace(err));
+          master()->handle_error(err);
       }
       PD("Terminating local backend\n");
       lock = 0;
@@ -1065,6 +1065,7 @@ class sql_result {
         _bindportal();
         conxsess bindbuffer = c->start();
         _unnamedstatementkey = 0;
+        stmtifkey = 0;
         CHAIN(bindbuffer)->add_int8('B')->add_hstring(plugbuffer, 4, 4);
         if (!_tprepared && sizeof(_preparedname))
           closestatement(CHAIN(bindbuffer), _preparedname);