--- clamd/server.h (revision 3538) +++ clamd/server.h (working copy) @@ -51,6 +51,18 @@ unsigned int options; }; +/* reload thread arguments */ +struct rthrarg { + struct cl_engine **engine; + const struct cfgstruct *copt; + unsigned int dboptions; +#ifdef CLAMUKO + pthread_t *clamuko_pid; + pthread_attr_t *clamuko_attr; + struct thrarg *tharg; +#endif +}; + int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigned int dboptions, const struct cfgstruct *copt); void sighandler(int sig); void sighandler_th(int sig); --- clamd/server-th.c (revision 3538) +++ clamd/server-th.c (working copy) @@ -66,10 +66,12 @@ int progexit = 0; pthread_mutex_t exit_mutex; int reload = 0; +int reloading = 0; time_t reloaded_time = 0; pthread_mutex_t reload_mutex; int sighup = 0; static struct cl_stat *dbstat = NULL; +pthread_mutex_t engine_mutex; typedef struct client_conn_tag { int sd; @@ -255,6 +257,51 @@ return engine; } +void reload_thread(void *arg) +{ + struct cl_engine *newengine = NULL; + struct cl_engine *oldengine = NULL; + struct rthrarg *args = (struct rthrarg *) arg; + int ret = 0; + + newengine = reload_db(newengine, args->dboptions, args->copt, FALSE, &ret); + if(ret) { + logg("Terminating because of a fatal error.\n"); + pthread_mutex_lock(&exit_mutex); + progexit = 1; + pthread_mutex_unlock(&exit_mutex); + pthread_exit(NULL); + } + + pthread_mutex_lock(&engine_mutex); + oldengine = *args->engine; + *args->engine = newengine; + pthread_mutex_unlock(&engine_mutex); + + if(oldengine) { + cl_free(oldengine); + oldengine = NULL; + } + + pthread_mutex_lock(&reload_mutex); + time(&reloaded_time); + reloading = 0; + pthread_mutex_unlock(&reload_mutex); + +#ifdef CLAMUKO + if(cfgopt(args->copt, "ClamukoScanOnAccess")->enabled) { + logg("Stopping and restarting Clamuko.\n"); + pthread_kill(*args->clamuko_pid, SIGUSR1); + pthread_join(*args->clamuko_pid, NULL); + pthread_mutex_lock(&engine_mutex); + args->tharg->engine = *args->engine; + pthread_mutex_unlock(&engine_mutex); + pthread_create(args->clamuko_pid, args->clamuko_attr, clamukoth, args->tharg); + } +#endif + pthread_exit(NULL); +} + int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigned int dboptions, const struct cfgstruct *copt) { int max_threads, i, ret = 0; @@ -288,6 +335,10 @@ struct thrarg *tharg = NULL; /* shut up gcc */ #endif + pthread_t reload_pid; + struct rthrarg *rthrargs; + int new_sd; + #ifndef C_WINDOWS memset(&sigact, 0, sizeof(struct sigaction)); #endif @@ -460,7 +511,9 @@ tharg = (struct thrarg *) malloc(sizeof(struct thrarg)); tharg->copt = copt; + pthread_mutex_lock(&engine_mutex); tharg->engine = engine; + pthread_mutex_unlock(&engine_mutex); tharg->limits = &limits; tharg->options = options; @@ -498,6 +551,7 @@ pthread_mutex_init(&exit_mutex, NULL); pthread_mutex_init(&reload_mutex, NULL); + pthread_mutex_init(&engine_mutex, NULL); idletimeout = cfgopt(copt, "IdleTimeout")->numarg; @@ -513,7 +567,7 @@ struct stat st_buf; #endif int socketd = socketds[0]; - int new_sd = 0; + new_sd = 0; if(nsockets > 1) { int pollret = poll_fds(socketds, nsockets, -1, 1); @@ -563,8 +617,12 @@ client_conn->sd = new_sd; client_conn->options = options; client_conn->copt = copt; + pthread_mutex_lock(&engine_mutex); + pthread_mutex_lock(&reload_mutex); client_conn->engine = cl_dup(engine); client_conn->engine_timestamp = reloaded_time; + pthread_mutex_unlock(&reload_mutex); + pthread_mutex_unlock(&engine_mutex); client_conn->limits = &limits; client_conn->socketds = socketds; client_conn->nsockets = nsockets; @@ -577,54 +635,62 @@ pthread_mutex_lock(&exit_mutex); if(progexit) { - if (new_sd >= 0) { - close(new_sd); - } pthread_mutex_unlock(&exit_mutex); break; } pthread_mutex_unlock(&exit_mutex); - if(selfchk) { + pthread_mutex_lock(&reload_mutex); + if(!reloading && selfchk) { + pthread_mutex_unlock(&reload_mutex); time(¤t_time); if((current_time - start_time) > (time_t)selfchk) { + pthread_mutex_lock(&engine_mutex); if(reload_db(engine, dboptions, copt, TRUE, &ret)) { + pthread_mutex_unlock(&engine_mutex); pthread_mutex_lock(&reload_mutex); reload = 1; pthread_mutex_unlock(&reload_mutex); + } else { + pthread_mutex_unlock(&engine_mutex); } time(&start_time); } + } else { + pthread_mutex_unlock(&reload_mutex); } pthread_mutex_lock(&reload_mutex); - if(reload) { + if(!reloading && reload) { + reloading = 1; + reload = 0; pthread_mutex_unlock(&reload_mutex); - engine = reload_db(engine, dboptions, copt, FALSE, &ret); - if(ret) { - logg("Terminating because of a fatal error.\n"); - if(new_sd >= 0) - close(new_sd); + rthrargs = (struct rthrarg *) malloc(sizeof(struct rthrarg)); + if(!rthrargs) { + logg("!Can't allocate memory for reload thread arguments\n"); break; } - pthread_mutex_lock(&reload_mutex); - reload = 0; - time(&reloaded_time); - pthread_mutex_unlock(&reload_mutex); + pthread_mutex_lock(&engine_mutex); + rthrargs->engine = &engine; + pthread_mutex_unlock(&engine_mutex); + rthrargs->copt = copt; + rthrargs->dboptions = dboptions; #ifdef CLAMUKO - if(cfgopt(copt, "ClamukoScanOnAccess")->enabled) { - logg("Stopping and restarting Clamuko.\n"); - pthread_kill(clamuko_pid, SIGUSR1); - pthread_join(clamuko_pid, NULL); - tharg->engine = engine; - pthread_create(&clamuko_pid, &clamuko_attr, clamukoth, tharg); - } + rthrargs->clamuko_pid = &clamuko_pid; + rthrargs->clamuko_attr = &clamuko_attr; + rthrargs->tharg = tharg; #endif + pthread_create(&reload_pid, NULL, reload_thread, (void *) rthrargs); + } else { pthread_mutex_unlock(&reload_mutex); } } + if (new_sd >= 0) { + close(new_sd); + } + /* Destroy the thread manager. * This waits for all current tasks to end */ @@ -636,8 +702,10 @@ pthread_join(clamuko_pid, NULL); } #endif + pthread_mutex_lock(&engine_mutex); if(engine) cl_free(engine); + pthread_mutex_unlock(&engine_mutex); if(dbstat) cl_statfree(dbstat);