mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
nwfilter: save error from DHCP snoop thread to report in main thread
A problem encountered due to a bug in libpcap was reported to the caller as: An error occurred, but the cause is unknown This was because the error had been logged in the DHCPSnoop thread. The worker thread handling the API call to start a domain spins up the DHCPSnoop thread which watches for dhcp packets with libpcap, then uses virCondSignal() to notify the worker thread (which has been waiting with virCondWait()). The worker thread knows that there was an error (because threadStatus != THREAD_STATUS_OK), but the error info had been stored in thread-specific storage for the other thread, so the worker thread can only report that there was a failure, but it doesn't know why. The solution is to save the error that was logged (with virErrorPreserveLast() into the object the is used to share info between the threads, then we can set the error in the worker thread using virErrorRestore(). In the case of the error I was looking at, this changed the "unknown" message into: internal error: pcap_setfilter: can't remove kernel filter: Bad file descriptor Signed-off-by: Laine Stump <laine@laine.org>
This commit is contained in:
parent
e1ab81b339
commit
1297db7414
@ -147,6 +147,7 @@ struct _virNWFilterSnoopReq {
|
|||||||
virNWFilterSnoopIPLeasePtr start;
|
virNWFilterSnoopIPLeasePtr start;
|
||||||
virNWFilterSnoopIPLeasePtr end;
|
virNWFilterSnoopIPLeasePtr end;
|
||||||
char *threadkey;
|
char *threadkey;
|
||||||
|
virErrorPtr threadError;
|
||||||
|
|
||||||
virNWFilterSnoopThreadStatus threadStatus;
|
virNWFilterSnoopThreadStatus threadStatus;
|
||||||
virCond threadStatusCond;
|
virCond threadStatusCond;
|
||||||
@ -639,6 +640,7 @@ virNWFilterSnoopReqFree(virNWFilterSnoopReqPtr req)
|
|||||||
|
|
||||||
virMutexDestroy(&req->lock);
|
virMutexDestroy(&req->lock);
|
||||||
virCondDestroy(&req->threadStatusCond);
|
virCondDestroy(&req->threadStatusCond);
|
||||||
|
virFreeError(req->threadError);
|
||||||
|
|
||||||
VIR_FREE(req);
|
VIR_FREE(req);
|
||||||
}
|
}
|
||||||
@ -1404,10 +1406,12 @@ virNWFilterDHCPSnoopThread(void *req0)
|
|||||||
|
|
||||||
/* let creator know how well we initialized */
|
/* let creator know how well we initialized */
|
||||||
if (error || !threadkey || tmp < 0 || !worker ||
|
if (error || !threadkey || tmp < 0 || !worker ||
|
||||||
ifindex != req->ifindex)
|
ifindex != req->ifindex) {
|
||||||
|
virErrorPreserveLast(&req->threadError);
|
||||||
req->threadStatus = THREAD_STATUS_FAIL;
|
req->threadStatus = THREAD_STATUS_FAIL;
|
||||||
else
|
} else {
|
||||||
req->threadStatus = THREAD_STATUS_OK;
|
req->threadStatus = THREAD_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
virCondSignal(&req->threadStatusCond);
|
virCondSignal(&req->threadStatusCond);
|
||||||
|
|
||||||
@ -1713,9 +1717,16 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* sync with thread */
|
/* sync with thread */
|
||||||
if (virCondWait(&req->threadStatusCond, &req->lock) < 0 ||
|
if (virCondWait(&req->threadStatusCond, &req->lock) < 0) {
|
||||||
req->threadStatus != THREAD_STATUS_OK)
|
virReportSystemError(errno, "%s",
|
||||||
|
_("unable to wait on dhcp snoop thread"));
|
||||||
goto exit_snoop_cancel;
|
goto exit_snoop_cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->threadStatus != THREAD_STATUS_OK) {
|
||||||
|
virErrorRestore(&req->threadError);
|
||||||
|
goto exit_snoop_cancel;
|
||||||
|
}
|
||||||
|
|
||||||
virNWFilterSnoopReqUnlock(req);
|
virNWFilterSnoopReqUnlock(req);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user