Browse code

clamonacc - cleanup event loop exiting; use pthread cancel push and pop macros for exiting to avoid signal collision issues with thread pool; whitespace

Mickey Sola authored on 2019/06/15 07:14:46
Showing 3 changed files
... ...
@@ -63,22 +63,24 @@ static void onas_fan_exit(int sig)
63 63
 {
64 64
 	logg("*ClamFanotif: onas_fan_exit(), signal %d\n", sig);
65 65
 
66
-        if(onas_fan_fd) {
67
-    close(onas_fan_fd);
68
-        }
69
-        onas_fan_fd = 0;
70
-
71
-    if (ddd_pid > 0) {
72
-        pthread_kill(ddd_pid, SIGUSR1);
73
-        pthread_join(ddd_pid, NULL);
74
-    }
75
-        ddd_pid = 0;
76
-
77
-        if (scque_pid > 0) {
78
-		pthread_kill(scque_pid, SIGUSR2);
66
+	if(onas_fan_fd) {
67
+		close(onas_fan_fd);
68
+	}
69
+	onas_fan_fd = 0;
70
+
71
+	logg("*ClamFanotif: attempting to stop event consumer thread ...\n");
72
+	if (scque_pid > 0) {
73
+		pthread_cancel(scque_pid);
79 74
 		pthread_join(scque_pid, NULL);
80
-    }
81
-        scque_pid = 0;
75
+	}
76
+	scque_pid = 0;
77
+
78
+	logg("*ClamFanotif: attempting to stop ddd thread ... \n");
79
+	if (ddd_pid > 0) {
80
+		pthread_cancel(ddd_pid);
81
+		pthread_join(ddd_pid, NULL);
82
+	}
83
+	ddd_pid = 0;
82 84
 
83 85
 	logg("ClamFanotif: stopped\n");
84 86
 	pthread_exit(NULL);
... ...
@@ -168,7 +170,7 @@ cl_error_t onas_setup_fanotif(struct onas_context **ctx) {
168 168
 
169 169
 int onas_fan_eloop(struct onas_context **ctx) {
170 170
 	int ret = 0;
171
-        int err_cnt = 0;
171
+	int err_cnt = 0;
172 172
 	sigset_t sigset;
173 173
 	struct sigaction act;
174 174
 	short int scan;
... ...
@@ -184,12 +186,14 @@ int onas_fan_eloop(struct onas_context **ctx) {
184 184
 	/* ignore all signals except SIGUSR1 */
185 185
 	sigfillset(&sigset);
186 186
 	sigdelset(&sigset, SIGUSR1);
187
+	sigdelset(&sigset, SIGUSR2);
187 188
 	/* The behavior of a process is undefined after it ignores a
188 189
 	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
189 190
 	sigdelset(&sigset, SIGFPE);
190 191
 	sigdelset(&sigset, SIGILL);
191 192
 	sigdelset(&sigset, SIGSEGV);
192 193
 	sigdelset(&sigset, SIGINT);
194
+	sigdelset(&sigset, SIGTERM);
193 195
 #ifdef SIGBUS
194 196
 	sigdelset(&sigset, SIGBUS);
195 197
 #endif
... ...
@@ -197,28 +201,31 @@ int onas_fan_eloop(struct onas_context **ctx) {
197 197
 	memset(&act, 0, sizeof(struct sigaction));
198 198
 	act.sa_handler = onas_fan_exit;
199 199
 	sigfillset(&(act.sa_mask));
200
-	sigaction(SIGUSR1, &act, NULL);
200
+	sigaction(SIGUSR2, &act, NULL);
201
+	sigaction(SIGTERM, &act, NULL);
201 202
 	sigaction(SIGSEGV, &act, NULL);
202 203
 	sigaction(SIGINT, &act, NULL);
203 204
 
204
-    FD_ZERO(&rfds);
205
+	FD_ZERO(&rfds);
205 206
 	FD_SET((*ctx)->fan_fd, &rfds);
206
-    do {
207
+
208
+        logg("*ClamFanotif: starting fanotify event loop with process id (%d) ... \n", getpid());
209
+	do {
207 210
 		ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL);
208 211
 	} while((ret == -1 && errno == EINTR));
209 212
 
210
-    time_t start = time(NULL) - 30;
213
+	time_t start = time(NULL) - 30;
211 214
 	while(((bread = read((*ctx)->fan_fd, buf, sizeof(buf))) > 0) || (errno == EOVERFLOW || errno == EMFILE || errno == EACCES)) {
212 215
 		switch(errno) {
213 216
 			case EOVERFLOW:
214
-            if (time(NULL) - start >= 30) {
217
+				if (time(NULL) - start >= 30) {
215 218
 					logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno));
216 219
 					logg("*ClamFanotif: file too large for fanotify ... recovering and continuing scans...\n");
217
-                start = time(NULL);
218
-            }
220
+					start = time(NULL);
221
+				}
219 222
 
220
-            errno = 0;
221
-            continue;
223
+				errno = 0;
224
+				continue;
222 225
 			case EACCES:
223 226
 				logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno));
224 227
 				logg("*ClamFanotif: check your SELinux audit logs and consider adding an exception \
... ...
@@ -228,113 +235,113 @@ int onas_fan_eloop(struct onas_context **ctx) {
228 228
 				continue;
229 229
 			case EMFILE:
230 230
 				logg("*ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno));
231
-                                logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n");
232
-                                sleep(3);
231
+				logg("*ClamFanotif: waiting for consumer thread to catch up then retrying ...\n");
232
+				sleep(3);
233 233
 
234 234
 				errno = 0;
235
-                                continue;
235
+				continue;
236 236
 			default:
237
-			break;
238
-                }
239
-
240
-        fmd = (struct fanotify_event_metadata *)buf;
241
-        while (FAN_EVENT_OK(fmd, bread)) {
242
-            scan = 1;
243
-            if (fmd->fd >= 0) {
244
-                sprintf(fname, "/proc/self/fd/%d", fmd->fd);
245
-                                errno = 0;
246
-                len = readlink(fname, fname, sizeof(fname) - 1);
247
-                if (len == -1) {
248
-                    close(fmd->fd);
237
+				break;
238
+		}
239
+
240
+		fmd = (struct fanotify_event_metadata *)buf;
241
+		while (FAN_EVENT_OK(fmd, bread)) {
242
+			scan = 1;
243
+			if (fmd->fd >= 0) {
244
+				sprintf(fname, "/proc/self/fd/%d", fmd->fd);
245
+				errno = 0;
246
+				len = readlink(fname, fname, sizeof(fname) - 1);
247
+				if (len == -1) {
248
+					close(fmd->fd);
249 249
 					logg("!ClamFanotif: internal error (readlink() failed), %d, %s\n", fmd->fd, strerror(errno));
250
-                                        if (errno == EBADF) {
251
-                                            logg("ClamWorker: fd already closed ... recovering ...\n");
252
-                                            continue;
253
-                                        } else {
254
-					return 2;
255
-                }
250
+					if (errno == EBADF) {
251
+						logg("ClamWorker: fd already closed ... recovering ...\n");
252
+						continue;
253
+					} else {
254
+						return 2;
255
+					}
256 256
 				}
257 257
 				fname[len] = '\0';
258 258
 
259 259
 				if((check = onas_fan_checkowner(fmd->pid, (*ctx)->clamdopts))) {
260
-                    scan = 0;
261
-                    if (check != CHK_SELF) {
262
-							logg("*ClamFanotif: %s skipped (excluded UID)\n", fname);
263
-                }
264
-            }
260
+					scan = 0;
261
+					if (check != CHK_SELF) {
262
+						logg("*ClamFanotif: %s skipped (excluded UID)\n", fname);
263
+					}
264
+				}
265 265
 
266
-                                if (scan) {
266
+				if (scan) {
267 267
 					struct onas_scan_event *event_data;
268 268
 
269 269
 					event_data = cli_calloc(1, sizeof(struct onas_scan_event));
270
-                                        if (NULL == event_data) {
271
-					    logg("!ClamFanotif: could not allocate memory for event data struct\n");
272
-                                            return 2;
273
-                                        }
270
+					if (NULL == event_data) {
271
+						logg("!ClamFanotif: could not allocate memory for event data struct\n");
272
+						return 2;
273
+					}
274 274
 
275
-                                        /* general mapping */
276
-                                        onas_map_context_info_to_event_data(*ctx, &event_data);
275
+					/* general mapping */
276
+					onas_map_context_info_to_event_data(*ctx, &event_data);
277 277
 					scan ? event_data->bool_opts |= ONAS_SCTH_B_SCAN : scan;
278 278
 
279
-                                        /* fanotify specific stuffs */
279
+					/* fanotify specific stuffs */
280 280
 					event_data->bool_opts |= ONAS_SCTH_B_FANOTIFY;
281
-                                        event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata));
282
-                                        if (NULL == event_data->fmd) {
283
-					    logg("!ClamFanotif: could not allocate memory for event data struct fmd\n");
284
-                                            return 2;
285
-                                        }
281
+					event_data->fmd = cli_malloc(sizeof(struct fanotify_event_metadata));
282
+					if (NULL == event_data->fmd) {
283
+						logg("!ClamFanotif: could not allocate memory for event data struct fmd\n");
284
+						return 2;
285
+					}
286 286
 					memcpy(event_data->fmd, fmd, sizeof(struct fanotify_event_metadata));
287
-                                        event_data->pathname = cli_strdup(fname);
287
+					event_data->pathname = cli_strdup(fname);
288 288
 
289 289
 
290 290
 					logg("*ClamFanotif: attempting to feed consumer queue\n");
291 291
 					/* feed consumer queue */
292 292
 					if (CL_SUCCESS != onas_queue_event(event_data)) {
293
-                close(fmd->fd);
293
+						close(fmd->fd);
294 294
 						logg("!ClamFanotif: error occurred while feeding consumer queue ... \n");
295
-                                                if ((*ctx)->retry_on_error) {
296
-                                                    err_cnt++;
297
-                                                    if (err_cnt < (*ctx)->retry_attempts) {
298
-                                                        logg("ClamFanotif: ... recovering ...\n");
299
-                                                        continue;
300
-                                                    }
301
-                                                }
295
+						if ((*ctx)->retry_on_error) {
296
+							err_cnt++;
297
+							if (err_cnt < (*ctx)->retry_attempts) {
298
+								logg("ClamFanotif: ... recovering ...\n");
299
+								continue;
300
+							}
301
+						}
302 302
 						return 2;
303 303
 					}
304
-                                } else {
305
-                                    if (fmd->mask & FAN_ALL_PERM_EVENTS) {
306
-                                        struct fanotify_response res;
304
+				} else {
305
+					if (fmd->mask & FAN_ALL_PERM_EVENTS) {
306
+						struct fanotify_response res;
307 307
 
308
-                                        res.fd = fmd->fd;
309
-                                        res.response = FAN_ALLOW;
308
+						res.fd = fmd->fd;
309
+						res.response = FAN_ALLOW;
310 310
 
311
-                                        if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) {
312
-						logg("!ClamFanotif: error occurred while excluding event\n");
313
-                                                return 2;
314
-                                        }
311
+						if (-1 == write((*ctx)->fan_fd, &res, sizeof(res))) {
312
+							logg("!ClamFanotif: error occurred while excluding event\n");
313
+							return 2;
314
+						}
315 315
 					}
316 316
 
317
-                                        if (-1 == close(fmd->fd)) {
317
+					if (-1 == close(fmd->fd)) {
318 318
 						logg("!ClamFanotif: error occurred while closing metadata fd, %d\n", fmd->fd);
319
-                                                if (errno == EBADF) {
320
-                                                    logg("ClamFanotif: fd already closed ... recovering ...\n");
321
-                                                } else {
322
-                                                return 2;
323
-                                        }
324
-                                    }
325
-                                }
326
-        }
327
-        fmd = FAN_EVENT_NEXT(fmd, bread);
328
-    }
329
-    do {
330
-				ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL);
319
+						if (errno == EBADF) {
320
+							logg("ClamFanotif: fd already closed ... recovering ...\n");
321
+						} else {
322
+							return 2;
323
+						}
324
+					}
325
+				}
326
+			}
327
+			fmd = FAN_EVENT_NEXT(fmd, bread);
328
+		}
329
+		do {
330
+			ret = select((*ctx)->fan_fd + 1, &rfds, NULL, NULL, NULL);
331 331
 		} while((ret == -1 && errno == EINTR));
332
-}
332
+	}
333 333
 
334
-		if(bread < 0) {
334
+	if(bread < 0) {
335 335
 		logg("!ClamFanotif: internal error (failed to read data) ... %s\n", strerror(errno));
336
-                        return 2;
337
-                }
336
+		return 2;
337
+	}
338 338
 
339 339
 
340 340
 	return ret;
... ...
@@ -74,8 +74,7 @@ static void onas_ddd_handle_in_create(struct onas_context *ctx, const char *path
74 74
 static void onas_ddd_handle_in_moved_from(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd);
75 75
 static void onas_ddd_handle_in_delete(struct onas_context *ctx, const char *path, const char *child_path, const struct inotify_event *event, int wd);
76 76
 static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char *pathname, int extra_options);
77
-
78
-static void onas_ddd_exit(int sig);
77
+static void onas_ddd_exit(void *arg);
79 78
 
80 79
 /* TODO: Unglobalize these. */
81 80
 static struct onas_ht *ddd_ht;
... ...
@@ -327,57 +326,52 @@ cl_error_t onas_enable_inotif_ddd(struct onas_context **ctx) {
327 327
 
328 328
 void *onas_ddd_th(void *arg) {
329 329
 	struct onas_context *ctx = (struct onas_context *) arg;
330
-    sigset_t sigset;
331
-    struct sigaction act;
332
-    const struct optstruct *pt;
333
-    uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
334
-    fd_set rfds;
335
-    char buf[4096];
336
-    ssize_t bread;
337
-    const struct inotify_event *event;
330
+	sigset_t sigset;
331
+	struct sigaction act;
332
+	const struct optstruct *pt;
333
+	uint64_t in_mask = IN_ONLYDIR | IN_MOVE | IN_DELETE | IN_CREATE;
334
+	fd_set rfds;
335
+	char buf[4096];
336
+	ssize_t bread;
337
+	const struct inotify_event *event;
338 338
 	int ret, len, idx;
339 339
 
340 340
 	char** include_list = NULL;
341 341
 	char** exclude_list = NULL;
342 342
 	int num_exdirs, num_indirs;
343
-        cl_error_t err;
343
+	cl_error_t err;
344 344
 
345
-    /* ignore all signals except SIGUSR1 */
346
-    sigfillset(&sigset);
347
-    sigdelset(&sigset, SIGUSR1);
348
-    /* The behavior of a process is undefined after it ignores a
345
+	/* ignore all signals */
346
+	sigfillset(&sigset);
347
+	sigdelset(&sigset, SIGUSR1);
348
+	sigdelset(&sigset, SIGUSR2);
349
+	/* The behavior of a process is undefined after it ignores a
349 350
 	 * SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal */
350
-    sigdelset(&sigset, SIGFPE);
351
-    sigdelset(&sigset, SIGILL);
352
-	sigdelset(&sigset, SIGSEGV);
351
+	sigdelset(&sigset, SIGFPE);
352
+	sigdelset(&sigset, SIGILL);
353
+	sigdelset(&sigset, SIGTERM);
353 354
 	sigdelset(&sigset, SIGINT);
354 355
 #ifdef SIGBUS
355
-    sigdelset(&sigset, SIGBUS);
356
+	sigdelset(&sigset, SIGBUS);
356 357
 #endif
357
-    pthread_sigmask(SIG_SETMASK, &sigset, NULL);
358
-    memset(&act, 0, sizeof(struct sigaction));
359
-    act.sa_handler = onas_ddd_exit;
360
-    sigfillset(&(act.sa_mask));
361
-    sigaction(SIGUSR1, &act, NULL);
362
-    sigaction(SIGSEGV, &act, NULL);
363 358
 
364
-        logg("*ClamInotif: starting inotify event thread\n");
359
+	logg("*ClamInotif: starting inotify event loop ...\n");
365 360
 
366
-    onas_in_fd = inotify_init1(IN_NONBLOCK);
367
-    if (onas_in_fd == -1) {
361
+	onas_in_fd = inotify_init1(IN_NONBLOCK);
362
+	if (onas_in_fd == -1) {
368 363
 		logg("!ClamInotif: could not init inotify\n");
369
-        return NULL;
370
-    }
364
+		return NULL;
365
+	}
371 366
 
372
-    ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
373
-    if (ret) {
367
+	ret = onas_ddd_init(0, ONAS_DEFAULT_HT_SIZE);
368
+	if (ret) {
374 369
 		logg("!ClamInotif: failed to initialize DDD system\n");
375
-        return NULL;
376
-    }
370
+		return NULL;
371
+	}
377 372
 
378 373
 
379 374
 	logg("*ClamInotif: dynamically determining directory hierarchy...\n");
380
-    /* Add provided paths recursively. */
375
+	/* Add provided paths recursively. */
381 376
 
382 377
 	if (!optget(ctx->opts, "watch-list")->enabled && !optget(ctx->clamdopts, "OnAccessIncludePath")->enabled) {
383 378
 		logg("!ClamInotif: Please specify at least one path with OnAccessIncludePath\n");
... ...
@@ -386,24 +380,24 @@ void *onas_ddd_th(void *arg) {
386 386
 
387 387
 	if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) {
388 388
 
389
-        while (pt) {
390
-            if (!strcmp(pt->strarg, "/")) {
389
+		while (pt) {
390
+			if (!strcmp(pt->strarg, "/")) {
391 391
 				logg("!ClamInotif: not including path '%s' while DDD is enabled\n", pt->strarg);
392 392
 				logg("!ClamInotif: please use the OnAccessMountPath option to watch '%s'\n", pt->strarg);
393
-                pt = (struct optstruct *)pt->nextarg;
394
-                continue;
395
-            }
396
-            if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
397
-                if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
393
+				pt = (struct optstruct *)pt->nextarg;
394
+				continue;
395
+			}
396
+			if (onas_ht_get(ddd_ht, pt->strarg, strlen(pt->strarg), NULL) != CL_SUCCESS) {
397
+				if (onas_ht_add_hierarchy(ddd_ht, pt->strarg)) {
398 398
 					logg("!ClamInotif: can't include '%s'\n", pt->strarg);
399
-                    return NULL;
399
+					return NULL;
400 400
 				} else {
401 401
 					logg("ClamInotif: watching '%s' (and all sub-directories)\n", pt->strarg);
402
-            }
402
+				}
403 403
 			}
404 404
 
405
-            pt = (struct optstruct *)pt->nextarg;
406
-        }
405
+			pt = (struct optstruct *)pt->nextarg;
406
+		}
407 407
 	}
408 408
 
409 409
 	if((pt = optget(ctx->opts, "watch-list"))->enabled) {
... ...
@@ -413,8 +407,8 @@ void *onas_ddd_th(void *arg) {
413 413
 
414 414
 		include_list = onas_get_opt_list(pt->strarg, &num_indirs, &err);
415 415
 		if (NULL == include_list) {
416
-        return NULL;
417
-    }
416
+			return NULL;
417
+		}
418 418
 
419 419
 		idx = 0;
420 420
 		while (NULL != include_list[idx]) {
... ...
@@ -432,21 +426,21 @@ void *onas_ddd_th(void *arg) {
432 432
 		}
433 433
 	}
434 434
 
435
-    /* Remove provided paths recursively. */
435
+	/* Remove provided paths recursively. */
436 436
 	if((pt = optget(ctx->clamdopts, "OnAccessExcludePath"))->enabled) {
437
-        while (pt) {
438
-            size_t ptlen = strlen(pt->strarg);
439
-            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
440
-                if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
437
+		while (pt) {
438
+			size_t ptlen = strlen(pt->strarg);
439
+			if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
440
+				if (onas_ht_rm_hierarchy(ddd_ht, pt->strarg, ptlen, 0)) {
441 441
 					logg("!ClamInotif: can't exclude '%s'\n", pt->strarg);
442
-                    return NULL;
443
-                } else
442
+					return NULL;
443
+				} else
444 444
 					logg("ClamInotif: excluding '%s' (and all sub-directories)\n", pt->strarg);
445
-            }
445
+			}
446 446
 
447
-            pt = (struct optstruct *)pt->nextarg;
448
-        }
449
-    }
447
+			pt = (struct optstruct *)pt->nextarg;
448
+		}
449
+	}
450 450
 
451 451
 	if((pt = optget(ctx->opts, "exclude-list"))->enabled) {
452 452
 
... ...
@@ -473,35 +467,35 @@ void *onas_ddd_th(void *arg) {
473 473
 		}
474 474
 	}
475 475
 
476
-    /* Watch provided paths recursively */
476
+	/* Watch provided paths recursively */
477 477
 	if((pt = optget(ctx->clamdopts, "OnAccessIncludePath"))->enabled) {
478
-        while (pt) {
478
+		while (pt) {
479 479
 			errno = 0;
480
-            size_t ptlen = strlen(pt->strarg);
481
-            if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
480
+			size_t ptlen = strlen(pt->strarg);
481
+			if (onas_ht_get(ddd_ht, pt->strarg, ptlen, NULL) == CL_SUCCESS) {
482 482
 				if(err = onas_ddd_watch(pt->strarg, ctx->fan_fd, ctx->fan_mask, onas_in_fd, in_mask)) {
483 483
 
484 484
 					if (0 == errno) {
485 485
 						logg("!ClamInotif: could not watch path '%s', %d\n ", pt->strarg, err);
486 486
 					} else {
487 487
 						logg("!ClamInotif: could not watch path '%s', %s\n", pt->strarg, strerror(errno));
488
-					if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) {
488
+						if(errno == EINVAL && optget(ctx->clamdopts, "OnAccessPrevention")->enabled) {
489 489
 							logg("*ClamInotif: when using the OnAccessPrevention option, please ensure your kernel\n\t\t\twas compiled with CONFIG_FANOTIFY_ACCESS_PERMISSIONS set to Y\n");
490 490
 
491
-                        kill(getpid(), SIGTERM);
492
-                    }
491
+							kill(getpid(), SIGTERM);
492
+						}
493 493
 						if (errno == ENOSPC) {
494 494
 
495 495
 							logg("*ClamInotif: you likely do not have enough inotify watchpoints available ... run the follow command to increase available watchpoints and try again ...\n");
496 496
 							logg("*\t $ echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p\n");
497 497
 
498 498
 							kill(getpid(), SIGTERM);
499
-                                                }
500
-                }
501
-            }
502
-            pt = (struct optstruct *)pt->nextarg;
503
-        }
504
-    }
499
+						}
500
+					}
501
+				}
502
+				pt = (struct optstruct *)pt->nextarg;
503
+			}
504
+		}
505 505
 	}
506 506
 
507 507
 	if(NULL != include_list) {
... ...
@@ -536,82 +530,85 @@ void *onas_ddd_th(void *arg) {
536 536
 
537 537
 	if(optget(ctx->clamdopts, "OnAccessExtraScanning")->enabled) {
538 538
 		logg("ClamInotif: extra scanning on inotify events enabled\n");
539
-}
540
-
541
-    FD_ZERO(&rfds);
542
-    FD_SET(onas_in_fd, &rfds);
543
-
544
-    while (1) {
545
-        do {
546
-            ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
547
-        } while (ret == -1 && errno == EINTR);
539
+	}
548 540
 
549
-        while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
541
+	FD_ZERO(&rfds);
542
+	FD_SET(onas_in_fd, &rfds);
550 543
 
551
-            /* Handle events. */
552
-            int wd;
553
-            char *p           = buf;
554
-            const char *path  = NULL;
555
-            const char *child = NULL;
556
-            for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
544
+	pthread_cleanup_push(onas_ddd_exit, NULL);
557 545
 
558
-                event = (const struct inotify_event *)p;
559
-                wd    = event->wd;
560
-                path  = wdlt[wd];
561
-                child = event->name;
546
+	while (1) {
547
+		do {
548
+			ret = select(onas_in_fd + 1, &rfds, NULL, NULL, NULL);
549
+		} while (ret == -1 && errno == EINTR);
550
+
551
+		while ((bread = read(onas_in_fd, buf, sizeof(buf))) > 0) {
552
+			pthread_testcancel();
553
+			/* Handle events. */
554
+			int wd;
555
+			char *p           = buf;
556
+			const char *path  = NULL;
557
+			const char *child = NULL;
558
+			for (; p < buf + bread; p += sizeof(struct inotify_event) + event->len) {
559
+
560
+				event = (const struct inotify_event *)p;
561
+				wd    = event->wd;
562
+				path  = wdlt[wd];
563
+				child = event->name;
562 564
 
563 565
 				if (path == NULL) {
564 566
 					logg("*ClamInotif: watch descriptor not found in lookup table ... skipping\n");
565 567
 					continue;
566 568
 				}
567 569
 
568
-                len              = strlen(path);
569
-                size_t size      = strlen(child) + len + 2;
570
-                char *child_path = (char *)cli_malloc(size);
570
+				len              = strlen(path);
571
+				size_t size      = strlen(child) + len + 2;
572
+				char *child_path = (char *)cli_malloc(size);
571 573
 				if (child_path == NULL) {
572 574
 					logg("*ClamInotif: could not allocate space for child path ... aborting\n");
573
-                    return NULL;
575
+					return NULL;
574 576
 				}
575 577
 
576 578
 				if (path[len-1] == '/') {
577
-                    snprintf(child_path, --size, "%s%s", path, child);
579
+					snprintf(child_path, --size, "%s%s", path, child);
578 580
 				} else {
579
-                    snprintf(child_path, size, "%s/%s", path, child);
581
+					snprintf(child_path, size, "%s/%s", path, child);
580 582
 				}
581 583
 
582
-                if (event->mask & IN_DELETE) {
584
+				if (event->mask & IN_DELETE) {
583 585
 					onas_ddd_handle_in_delete(ctx, path, child_path, event, wd);
584 586
 
585
-                } else if (event->mask & IN_MOVED_FROM) {
587
+				} else if (event->mask & IN_MOVED_FROM) {
586 588
 					onas_ddd_handle_in_moved_from(ctx, path, child_path, event, wd);
587 589
 
588
-                } else if (event->mask & IN_CREATE) {
590
+				} else if (event->mask & IN_CREATE) {
589 591
 					onas_ddd_handle_in_create(ctx, path, child_path, event, wd, in_mask);
590 592
 
591
-                } else if (event->mask & IN_MOVED_TO) {
593
+				} else if (event->mask & IN_MOVED_TO) {
592 594
 					onas_ddd_handle_in_moved_to(ctx, path, child_path, event, wd, in_mask);
593
-                }
594
-            }
595
-        }
596
-    }
595
+				}
596
+			}
597
+		}
598
+	}
597 599
 
598
-        logg("*ClamInotif: exiting inotify event thread\n");
599
-    return NULL;
600
+	logg("*ClamInotif: exiting inotify event thread\n");
601
+	pthread_cleanup_pop(1);
602
+	return NULL;
600 603
 }
601 604
 
602 605
 
603 606
 static void onas_ddd_handle_in_delete(struct onas_context *ctx,
604 607
 		const char *path, const char *child_path, const struct inotify_event *event, int wd) {
605 608
 
606
-    struct stat s;
607
-    if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
608
-    if (!(event->mask & IN_ISDIR)) return;
609
+	struct stat s;
610
+	if (stat(child_path, &s) == 0 && S_ISREG(s.st_mode)) return;
611
+	if (!(event->mask & IN_ISDIR)) return;
609 612
 
610 613
 	logg("*ClamInotif: DELETE - removing %s from %s with wd:%d\n", child_path, path, wd);
611 614
 	onas_ddd_unwatch(child_path, ctx->fan_fd, onas_in_fd);
612
-    onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
615
+	onas_ht_rm_hierarchy(ddd_ht, child_path, strlen(child_path), 0);
613 616
 
614
-    return;
617
+	return;
615 618
 }
616 619
 
617 620
 static void onas_ddd_handle_in_moved_from(struct onas_context *ctx,
... ...
@@ -716,25 +713,25 @@ static void onas_ddd_handle_extra_scanning(struct onas_context *ctx, const char
716 716
     return;
717 717
 }
718 718
 
719
-static void onas_ddd_exit(int sig) {
720
-	logg("*ClamInotif: onas_ddd_exit(), signal %d\n", sig);
719
+static void onas_ddd_exit(void *arg) {
720
+	logg("*ClamInotif: onas_ddd_exit()\n");
721 721
 
722
-        if (onas_in_fd) {
723
-    close(onas_in_fd);
724
-        }
725
-        onas_in_fd = 0;
722
+	if (onas_in_fd) {
723
+		close(onas_in_fd);
724
+	}
725
+	onas_in_fd = 0;
726 726
 
727 727
 	if (ddd_ht) {
728
-    onas_free_ht(ddd_ht);
729
-        }
730
-        ddd_ht = NULL;
728
+		onas_free_ht(ddd_ht);
729
+	}
730
+	ddd_ht = NULL;
731 731
 
732
-        if (wdlt) {
733
-    free(wdlt);
734
-        }
735
-        wdlt = NULL;
732
+	if (wdlt) {
733
+		free(wdlt);
734
+	}
735
+	wdlt = NULL;
736 736
 
737 737
 	logg("ClamInotif: stopped\n");
738
-	pthread_exit(NULL);
739 738
 }
739
+
740 740
 #endif
... ...
@@ -44,7 +44,7 @@
44 44
 #include "./onaccess_scth.h"
45 45
 #include "./onaccess_scque.h"
46 46
 
47
-static void onas_scanque_exit(int sig);
47
+static void onas_scanque_exit(void * arg);
48 48
 static int onas_consume_event(threadpool thpool);
49 49
 static cl_error_t onas_new_event_queue_node(struct onas_event_queue_node **node);
50 50
 static void onas_destroy_event_queue_node(struct onas_event_queue_node *node);
... ...
@@ -121,6 +121,10 @@ static void onas_destroy_event_queue_node(struct onas_event_queue_node *node) {
121 121
 
122 122
 static void onas_destroy_event_queue() {
123 123
 
124
+	if (NULL == g_onas_event_queue_head) {
125
+		return;
126
+	}
127
+
124 128
 	struct onas_event_queue_node *curr = g_onas_event_queue_head;
125 129
 	struct onas_event_queue_node *next = curr->next;
126 130
 
... ...
@@ -147,7 +151,7 @@ void *onas_scanque_th(void *arg) {
147 147
 
148 148
         cl_error_t err;
149 149
 
150
-	/* ignore all signals except SIGUSR1 */
150
+	/* ignore all signals except SIGUSR2 */
151 151
 	sigfillset(&sigset);
152 152
 	sigdelset(&sigset, SIGUSR2);
153 153
 	/* The behavior of a process is undefined after it ignores a
... ...
@@ -155,16 +159,11 @@ void *onas_scanque_th(void *arg) {
155 155
 	sigdelset(&sigset, SIGFPE);
156 156
 	sigdelset(&sigset, SIGILL);
157 157
 	sigdelset(&sigset, SIGSEGV);
158
+	sigdelset(&sigset, SIGTERM);
158 159
 	sigdelset(&sigset, SIGINT);
159 160
 #ifdef SIGBUS
160 161
 	sigdelset(&sigset, SIGBUS);
161 162
 #endif
162
-	pthread_sigmask(SIG_SETMASK, &sigset, NULL);
163
-	memset(&act, 0, sizeof(struct sigaction));
164
-	act.sa_handler = onas_scanque_exit;
165
-	sigfillset(&(act.sa_mask));
166
-	sigaction(SIGUSR2, &act, NULL);
167
-	sigaction(SIGSEGV, &act, NULL);
168 163
 
169 164
 	logg("*ClamQueue: initializing event queue consumer ... (%d) threads in thread pool\n", ctx->maxthreads);
170 165
         onas_init_event_queue();
... ...
@@ -172,20 +171,21 @@ void *onas_scanque_th(void *arg) {
172 172
 	g_thpool = thpool;
173 173
 
174 174
         /* loop w/ onas_consume_event until we die */
175
+        pthread_cleanup_push(onas_scanque_exit, NULL);
175 176
 	logg("*ClamQueue: waiting to consume events ...\n");
176 177
 	do {
177
-            pthread_mutex_lock(&onas_scque_loop);
178
-            pthread_cond_wait(&onas_scque_empty_cond, &onas_scque_loop);
179
-            /* run 'till we're empty */
178
+		pthread_mutex_lock(&onas_scque_loop);
179
+		pthread_cond_wait(&onas_scque_empty_cond, &onas_scque_loop);
180
+		/* run 'till we're empty */
180 181
 		do {
181
-                    ret = onas_consume_event(thpool);
182
-                } while (1 != ret);
183
-            pthread_mutex_unlock(&onas_scque_loop);
184
-
185
-
182
+			pthread_testcancel();
183
+			ret = onas_consume_event(thpool);
184
+		} while (1 != ret);
185
+		pthread_mutex_unlock(&onas_scque_loop);
186 186
 
187 187
 	} while(1);
188 188
 
189
+	pthread_cleanup_pop(1);
189 190
 }
190 191
 
191 192
 static int onas_queue_is_b_empty() {
... ...
@@ -282,17 +282,19 @@ cl_error_t onas_scanque_start(struct onas_context **ctx) {
282 282
 	return CL_SUCCESS;
283 283
 }
284 284
 
285
-static void onas_scanque_exit(int sig) {
285
+static void onas_scanque_exit(void *arg) {
286 286
 
287
-	logg("*ClamScanque: onas_scanque_exit(), signal %d\n", sig);
287
+	logg("*ClamScanque: onas_scanque_exit()\n");
288 288
 
289
+	pthread_mutex_lock(&onas_queue_lock);
289 290
 	onas_destroy_event_queue();
291
+
290 292
         if (g_thpool) {
291 293
             thpool_destroy(g_thpool);
292 294
         }
293 295
         g_thpool = NULL;
296
+	pthread_mutex_unlock(&onas_queue_lock);
294 297
 
295 298
 	logg("ClamScanque: stopped\n");
296
-	pthread_exit(NULL);
297 299
 }
298 300