]> xenbits.xensource.com Git - libvirt.git/commitdiff
fdstream: Report error from the I/O thread
authorMichal Privoznik <mprivozn@redhat.com>
Mon, 29 May 2017 14:29:36 +0000 (16:29 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 11 Jul 2017 06:41:01 +0000 (08:41 +0200)
Problem with our error reporting is that the error object is a
thread local variable. That means if there's an error reported
within the I/O thread it gets logged and everything, but later
when the event loop aborts the stream it doesn't see the original
error. So we are left with some generic error. We can do better
if we copy the error message between the threads.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
daemon/stream.c
src/util/virfdstream.c

index 1d5b50ad7616f45a43f7ad142602da2c74f71d53..5077ac8b0af541c40bf8a36f2503a11fd70c1ce0 100644 (file)
@@ -231,17 +231,23 @@ daemonStreamEvent(virStreamPtr st, int events, void *opaque)
         int ret;
         virNetMessagePtr msg;
         virNetMessageError rerr;
+        virErrorPtr origErr = virSaveLastError();
 
         memset(&rerr, 0, sizeof(rerr));
         stream->closed = true;
         virStreamEventRemoveCallback(stream->st);
         virStreamAbort(stream->st);
-        if (events & VIR_STREAM_EVENT_HANGUP)
-            virReportError(VIR_ERR_RPC,
-                           "%s", _("stream had unexpected termination"));
-        else
-            virReportError(VIR_ERR_RPC,
-                           "%s", _("stream had I/O failure"));
+        if (origErr && origErr->code != VIR_ERR_OK) {
+            virSetError(origErr);
+            virFreeError(origErr);
+        } else {
+            if (events & VIR_STREAM_EVENT_HANGUP)
+                virReportError(VIR_ERR_RPC,
+                               "%s", _("stream had unexpected termination"));
+            else
+                virReportError(VIR_ERR_RPC,
+                               "%s", _("stream had I/O failure"));
+        }
 
         msg = virNetMessageNew(false);
         if (!msg) {
index bd2355d17f1122d52d9f39a3148eb5e41b9bb04f..f54ba15aeea09e7fe179348722da5d4a219db8ec 100644 (file)
@@ -106,7 +106,7 @@ struct virFDStreamData {
     /* Thread data */
     virThreadPtr thread;
     virCond threadCond;
-    int threadErr;
+    virErrorPtr threadErr;
     bool threadQuit;
     bool threadAbort;
     bool threadDoRead;
@@ -123,6 +123,7 @@ virFDStreamDataDispose(void *obj)
     virFDStreamDataPtr fdst = obj;
 
     VIR_DEBUG("obj=%p", fdst);
+    virFreeError(fdst->threadErr);
     virFDStreamMsgQueueFree(&fdst->msg);
 }
 
@@ -312,8 +313,10 @@ static void virFDStreamEvent(int watch ATTRIBUTE_UNUSED,
         return;
     }
 
-    if (fdst->threadErr)
+    if (fdst->threadErr) {
         events |= VIR_STREAM_EVENT_ERROR;
+        virSetError(fdst->threadErr);
+    }
 
     cb = fdst->cb;
     cbopaque = fdst->opaque;
@@ -641,7 +644,7 @@ virFDStreamThread(void *opaque)
     return;
 
  error:
-    fdst->threadErr = errno;
+    fdst->threadErr = virSaveLastError();
     goto cleanup;
 }