From a3d2f4261ef9a953904e3e21abafba0dad7daa77 Mon Sep 17 00:00:00 2001 From: gaoyi Date: Mon, 28 Sep 2020 22:36:37 +0800 Subject: [PATCH] Retry to handle the uevent when worker is terminated abnormal When processing uevent events fails, retry it. --- src/udev/udevd.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index c6d24d9..512192e 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -74,6 +74,7 @@ #include "version.h" #define WORKER_NUM_MAX 2048U +#define UEVENT_MAX_RETRY_TIMES 3 #define EVENT_RETRY_INTERVAL_USEC (200 * USEC_PER_MSEC) #define EVENT_RETRY_TIMEOUT_USEC (3 * USEC_PER_MINUTE) @@ -129,6 +130,7 @@ typedef struct Event { Manager *manager; Worker *worker; EventState state; + int retry; sd_device *dev; @@ -182,6 +184,32 @@ typedef enum EventResult { _EVENT_RESULT_INVALID = -EINVAL, } EventResult; +static bool event_retry(Event *event) { + if (!event) + return false; + + assert(event->manager); + + if (--event->retry < 0) { + log_device_error(event->dev, "Retry failed."); + return false; + } + + log_device_info(event->dev, "Retry %d times.", UEVENT_MAX_RETRY_TIMES - event->retry); + + event->timeout_warning_event = sd_event_source_unref(event->timeout_warning_event); + event->timeout_event = sd_event_source_unref(event->timeout_event); + + if (event->worker) { + event->worker->event = NULL; + event->worker = NULL; + } + + event->state = EVENT_QUEUED; + + return true; +} + static Event *event_free(Event *event) { if (!event) return NULL; @@ -1140,6 +1168,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { .devpath_old = devpath_old, .devnode = devnode, .state = EVENT_QUEUED, + .retry = UEVENT_MAX_RETRY_TIMES, }; if (!manager->events) { @@ -1513,8 +1542,10 @@ static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata) { device_delete_db(dev); device_tag_index(dev, NULL, false); - /* Forward kernel event to libudev listeners */ - device_broadcast(manager->monitor, dev, result); + if (event_retry(worker->event) == false) { + /* Forward kernel event to libudev listeners */ + device_broadcast(manager->monitor, worker->event->dev, result); + } } worker_free(worker); -- 2.33.0