Fix clamd hang when number of multiscan commands == MaxThreads (bb #1700).

Each multiscan command needs 1 control thread, and 1 (possibly shared) scanner
thread.
If the number of multiscan control threads would be equal to MaxThreads no
progress could be made, since each one would be waiting for 1 free scanner
thread (but none can be spawned since maxthreads was already reached).
As long as there is 1 thread free for scanning, we can have N-1 multiscan
commands active, with N MaxThreads.
0.96
Török Edvin 16 years ago
parent 3f25b35db9
commit 80301d0cd6
  1. 26
      clamd/session.c
  2. 1
      clamd/thrmgr.c
  3. 1
      clamd/thrmgr.h

@ -220,7 +220,27 @@ int command(client_conn_t *conn, int *virus)
thrmgr_setactivetask(NULL, "CONTSCAN");
type = TYPE_CONTSCAN;
break;
case COMMAND_MULTISCAN:
case COMMAND_MULTISCAN: {
int multiscan, max, alive;
pthread_mutex_lock(&conn->thrpool->pool_mutex);
multiscan = conn->thrpool->thr_multiscan;
max = conn->thrpool->thr_max;
if (multiscan+1 < max)
conn->thrpool->thr_multiscan = multiscan+1;
else {
alive = conn->thrpool->thr_alive;
ret = -1;
}
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
if (ret) {
// multiscan has 1 control thread, so there needs to be at least
// 1 threads that is a non-multiscan controlthread to scan and
// make progress.
logg("^Not enough threads for multiscan. Max: %d, Alive: %d, Multiscan: %d+1\n",
max, alive, multiscan);
conn_reply(conn, conn->filename, "Not enough threads for multiscan. Increase MaxThreads.","ERROR");
return 1;
}
flags &= ~CLI_FTW_NEED_STAT;
thrmgr_setactivetask(NULL, "MULTISCAN");
type = TYPE_MULTISCAN;
@ -228,6 +248,7 @@ int command(client_conn_t *conn, int *virus)
if (!group)
return CL_EMEM;
break;
}
case COMMAND_MULTISCANFILE:
thrmgr_setactivetask(NULL, "MULTISCANFILE");
scandata.group = NULL;
@ -324,6 +345,9 @@ int command(client_conn_t *conn, int *virus)
return -1;
if (scandata.group && conn->cmdtype == COMMAND_MULTISCAN) {
thrmgr_group_waitforall(group, &ok, &error, &total);
pthread_mutex_lock(&conn->thrpool->pool_mutex);
conn->thrpool->thr_multiscan--;
pthread_mutex_unlock(&conn->thrpool->pool_mutex);
} else {
error = scandata.errors;
total = scandata.total;

@ -387,6 +387,7 @@ threadpool_t *thrmgr_new(int max_threads, int idle_timeout, int max_queue, void
threadpool->thr_max = max_threads;
threadpool->thr_alive = 0;
threadpool->thr_idle = 0;
threadpool->thr_multiscan = 0;
threadpool->idle_timeout = idle_timeout;
threadpool->handler = handler;
threadpool->tasks = NULL;

@ -69,6 +69,7 @@ typedef struct threadpool_tag {
int queue_max;
int thr_alive;
int thr_idle;
int thr_multiscan;
int idle_timeout;
struct task_desc *tasks;

Loading…
Cancel
Save