Browse code

c4w: retry del_instance.

Caller can't wait for the proper scanner threads to finish for some reason.
Retry the del_instance once after 1 scanner thread finished (not necesarely the
one we got called for though).
If we still fail to delete Caller will retry after 2 seconds, and if we still
fail just go on and Uninit us (of course we'll fail there too, but its shutdown
anyway).

Also terminate monitor thread prior to freeing engine, because if engine can't
be freed we'd never even try to stop monitor thread.

Török Edvin authored on 2010/12/08 18:45:56
Showing 2 changed files
... ...
@@ -398,7 +398,17 @@ int CLAMAPI Scan_Uninitialize(void) {
398 398
 	unlock_engine();
399 399
 	FAIL(CL_ESTATE, "attempted to uninit a NULL engine");
400 400
     }
401
-   if(lock_instances()) {
401
+
402
+    if(monitor_hdl) {
403
+	SetEvent(monitor_event);
404
+	if(WaitForSingleObject(monitor_hdl, 5000) != WAIT_OBJECT_0) {
405
+	    logg("Scan_Uninitialize: forcibly terminating monitor thread after 5 seconds\n");
406
+	    TerminateThread(monitor_hdl, 0);
407
+	}
408
+    }
409
+    monitor_hdl = NULL;
410
+
411
+    if(lock_instances()) {
402 412
 	unlock_engine();
403 413
 	FAIL(CL_ELOCK, "failed to lock instances");
404 414
     }
... ...
@@ -411,14 +421,6 @@ int CLAMAPI Scan_Uninitialize(void) {
411 411
     unlock_instances();
412 412
     free_engine_and_unlock();
413 413
 
414
-    if(monitor_hdl) {
415
-	SetEvent(monitor_event);
416
-	if(WaitForSingleObject(monitor_hdl, 5000) != WAIT_OBJECT_0) {
417
-	    logg("Scan_Uninitialize: forcibly terminating monitor thread after 60 seconds\n");
418
-	    TerminateThread(monitor_hdl, 0);
419
-	}
420
-    }
421
-    monitor_hdl = NULL;
422 414
     WIN();
423 415
 }
424 416
 
... ...
@@ -452,13 +454,24 @@ int CLAMAPI Scan_CreateInstance(CClamAVScanner **ppScanner) {
452 452
     WIN();
453 453
 }
454 454
 
455
+// Caller: if we return error will retry once after 2 seconds.
456
+// No point in retrying more times since we are shutting down anyway.
455 457
 int CLAMAPI Scan_DestroyInstance(CClamAVScanner *pScanner) {
456 458
     int rc;
457 459
     INFN();
458 460
     if(!pScanner)
459 461
 	FAIL(CL_ENULLARG, "NULL pScanner");
460
-    if((rc = del_instance((instance *)pScanner)))
461
-	FAIL(rc, "del_instance failed for %p", pScanner);
462
+    if((rc = del_instance((instance *)pScanner))) {
463
+	if (rc == CL_EBUSY) {
464
+	    // wait for one of the scanner threads to finish, and retry again,
465
+	    // thats better than caller always waiting 2 seconds to retry.
466
+	    if (WaitForSingleObject(reload_event, 1000) != WAIT_OBJECT_0)
467
+		logg("Scan_DestroyInstance: timeout");
468
+	    rc = del_instance((instance *)pScanner);
469
+	}
470
+	if (rc)
471
+	    FAIL(rc, "del_instance failed for %p", pScanner);
472
+    }
462 473
     free(pScanner);
463 474
     logg("in Scan_DestroyInstance: Instance %p destroyed\n", pScanner);
464 475
     WIN();
... ...
@@ -99,7 +99,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReser
99 99
 	    // deadlock
100 100
 	    if (engine) {
101 101
 		if (uninitialize_called)
102
-		    fprintf(logg_fp, "Engine still active during detach! (we are probably going to crash now)\n");
102
+		    fprintf(logg_fp, "Engine still active during detach!\n");
103 103
 		else
104 104
 		    fprintf(logg_fp, "Scan_Uninitialize not called, but process is terminating\n");
105 105
 	    }