]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
nwfilter: Fix learning address thread shutdown
authorNikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Fri, 12 Oct 2018 07:23:07 +0000 (10:23 +0300)
committerJohn Ferlan <jferlan@redhat.com>
Wed, 17 Oct 2018 21:06:04 +0000 (17:06 -0400)
If the learning thread is configured to learn on all ethernet frames
(which is hardcoded) then chances are high that there is a packet on
every iteration of inspecting frames loop. As result we will hang on
shutdown because we don't check threadsTerminate if there is packet.

Let's just check termination conditions on every iteration. Since
we'll check each iteration, the check after pcap_next essentially
is unnecessary since on failure we'd loop back to the top and timeout
and then fail.

Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
Reviewed-by: John Ferlan <jferlan@redhat.com>
src/nwfilter/nwfilter_learnipaddr.c

index 008c24bc14b470d1d00087b6807e0dfeedaa536b..e6cb9964ac1fee61f7db616bcfb56ac1fbbf72c8 100644 (file)
@@ -483,6 +483,12 @@ learnIPAddressThread(void *arg)
     while (req->status == 0 && vmaddr == 0) {
         int n = poll(fds, ARRAY_CARDINALITY(fds), PKT_TIMEOUT_MS);
 
+        if (threadsTerminate || req->terminate) {
+            req->status = ECANCELED;
+            showError = false;
+            break;
+        }
+
         if (n < 0) {
             if (errno == EAGAIN || errno == EINTR)
                 continue;
@@ -492,15 +498,8 @@ learnIPAddressThread(void *arg)
             break;
         }
 
-        if (n == 0) {
-            if (threadsTerminate || req->terminate) {
-                VIR_DEBUG("Terminate request seen, cancelling pcap");
-                req->status = ECANCELED;
-                showError = false;
-                break;
-            }
+        if (n == 0)
             continue;
-        }
 
         if (fds[0].revents & (POLLHUP | POLLERR)) {
             VIR_DEBUG("Error from FD probably dev deleted");
@@ -512,13 +511,6 @@ learnIPAddressThread(void *arg)
         packet = pcap_next(handle, &header);
 
         if (!packet) {
-            /* Already handled with poll, but lets be sure */
-            if (threadsTerminate || req->terminate) {
-                req->status = ECANCELED;
-                showError = false;
-                break;
-            }
-
             /* Again, already handled above, but lets be sure */
             if (virNetDevValidateConfig(req->binding->portdevname, NULL, req->ifindex) <= 0) {
                 virResetLastError();