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.
... | ... |
@@ -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 |
} |