+ /* set signal handlers */
+ memset(&act, 0x00, sizeof(act));
+ act.sa_handler = event_sig_handler;
+ sigemptyset (&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGALRM, &act, NULL);
+
+ /* unblock SIGALRM */
+ sigfillset(&sigmask);
+ sigdelset(&sigmask, SIGALRM);
+ sigprocmask(SIG_SETMASK, &sigmask, NULL);
+ /* SIGTERM is unblocked in ppoll() */
+ sigdelset(&sigmask, SIGTERM);
+
+ /* request TERM signal if parent exits */
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+
+ /* initial device */
+ dev = event->dev;
+
+ do {
+ struct udev_event *udev_event;
+ struct worker_message msg = {};
+ int err;
+ int failed = 0;
+
+ info(event->udev, "seq %llu running\n", udev_device_get_seqnum(dev));
+ udev_event = udev_event_new(dev);
+ if (udev_event == NULL)
+ _exit(3);
+
+ /* set timeout to prevent hanging processes */
+ alarm(UDEV_EVENT_TIMEOUT);
+
+ /* apply rules, create node, symlinks */
+ err = udev_event_execute_rules(udev_event, rules);
+
+ /* rules may change/disable the timeout */
+ if (udev_device_get_event_timeout(dev) >= 0)
+ alarm(udev_device_get_event_timeout(dev));
+
+ /* execute RUN= */
+ if (err == 0 && !udev_event->ignore_device && udev_get_run(udev_event->udev))
+ failed = udev_event_execute_run(udev_event);
+
+ /* reset alarm */
+ alarm(0);
+
+ /* apply/restore inotify watch */
+ if (err == 0 && udev_event->inotify_watch) {
+ udev_watch_begin(udev_event->udev, dev);
+ udev_device_update_db(dev);
+ }
+
+ /* send processed event back to libudev listeners */
+ udev_monitor_send_device(worker_monitor, NULL, dev);
+
+ /* send back the result of the event execution */
+ if (err != 0)
+ msg.exitcode = err;
+ else if (failed != 0)
+ msg.exitcode = failed;
+ msg.pid = getpid();
+ send(worker_watch[WRITE_END], &msg, sizeof(struct worker_message), 0);
+
+ info(event->udev, "seq %llu processed with %i\n", udev_device_get_seqnum(dev), err);
+ udev_event_unref(udev_event);
+ udev_device_unref(dev);
+ dev = NULL;
+
+ /* wait for more device messages or signal from udevd */
+ while (!worker_exit) {
+ int fdcount;
+
+ fdcount = ppoll(&pmon, 1, NULL, &sigmask);
+ if (fdcount < 0)
+ continue;
+
+ if (pmon.revents & POLLIN) {
+ dev = udev_monitor_receive_device(worker_monitor);
+ if (dev != NULL)
+ break;
+ }
+ }
+ } while (dev != NULL);