typedef struct Worker {
Manager *manager;
- pid_t pid;
+ PidRef pidref;
sd_event_source *child_event_source;
union sockaddr_union address;
WorkerState state;
return NULL;
if (worker->manager)
- hashmap_remove(worker->manager->workers, PID_TO_PTR(worker->pid));
+ hashmap_remove(worker->manager->workers, &worker->pidref);
- sd_event_source_unref(worker->child_event_source);
+ sd_event_source_disable_unref(worker->child_event_source);
+ pidref_done(&worker->pidref);
event_free(worker->event);
return mfree(worker);
DEFINE_TRIVIAL_CLEANUP_FUNC(Worker*, worker_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
worker_hash_op,
- void,
- trivial_hash_func,
- trivial_compare_func,
+ PidRef,
+ pidref_hash_func,
+ pidref_compare_func,
Worker,
worker_free);
static int on_sigchld(sd_event_source *s, const siginfo_t *si, void *userdata);
-static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) {
+static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, PidRef *pidref) {
_cleanup_(worker_freep) Worker *worker = NULL;
int r;
assert(ret);
assert(manager);
assert(worker_monitor);
- assert(pid > 1);
+ assert(pidref);
+
+ /* This takes and invalidates pidref even on some error cases. */
worker = new(Worker, 1);
if (!worker)
return -ENOMEM;
*worker = (Worker) {
- .pid = pid,
+ .pidref = TAKE_PIDREF(*pidref),
};
r = device_monitor_get_address(worker_monitor, &worker->address);
if (r < 0)
return r;
- r = sd_event_add_child(manager->event, &worker->child_event_source, pid, WEXITED, on_sigchld, worker);
+ r = event_add_child_pidref(manager->event, &worker->child_event_source, &worker->pidref, WEXITED, on_sigchld, worker);
if (r < 0)
return r;
- r = hashmap_ensure_put(&manager->workers, &worker_hash_op, PID_TO_PTR(pid), worker);
+ r = hashmap_ensure_put(&manager->workers, &worker_hash_op, &worker->pidref, worker);
if (r < 0)
return r;
}
worker->state = WORKER_KILLED;
- (void) kill(worker->pid, SIGTERM);
+ (void) pidref_kill(&worker->pidref, SIGTERM);
}
}
assert(event->manager);
assert(event->worker);
- kill_and_sigcont(event->worker->pid, event->manager->config.timeout_signal);
+ (void) pidref_kill_and_sigcont(&event->worker->pidref, event->manager->config.timeout_signal);
event->worker->state = WORKER_KILLED;
- log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed", event->worker->pid, event->seqnum);
+ log_device_error(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" killed.", event->worker->pidref.pid, event->seqnum);
return 1;
}
assert(event->worker);
- log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time", event->worker->pid, event->seqnum);
+ log_device_warning(event->dev, "Worker ["PID_FMT"] processing SEQNUM=%"PRIu64" is taking a long time.", event->worker->pidref.pid, event->seqnum);
return 1;
}
}
static int worker_spawn(Manager *manager, Event *event) {
- _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *worker_monitor = NULL;
- Worker *worker;
- pid_t pid;
int r;
+ assert(manager);
+ assert(event);
+
/* listen for new events */
- r = device_monitor_new_full(&worker_monitor, MONITOR_GROUP_NONE, -1);
+ _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *worker_monitor = NULL;
+ r = device_monitor_new_full(&worker_monitor, MONITOR_GROUP_NONE, -EBADF);
if (r < 0)
return r;
if (r < 0)
return log_error_errno(r, "Worker: Failed to set unicast sender: %m");
- r = safe_fork("(udev-worker)", FORK_DEATHSIG_SIGTERM, &pid);
+ _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+ r = pidref_safe_fork("(udev-worker)", FORK_DEATHSIG_SIGTERM, &pidref);
if (r < 0) {
event->state = EVENT_QUEUED;
return log_error_errno(r, "Failed to fork() worker: %m");
_exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
- r = worker_new(&worker, manager, worker_monitor, pid);
+ Worker *worker;
+ r = worker_new(&worker, manager, worker_monitor, &pidref);
if (r < 0)
return log_error_errno(r, "Failed to create worker object: %m");
worker_attach_event(worker, event);
- log_device_debug(event->dev, "Worker ["PID_FMT"] is forked for processing SEQNUM=%"PRIu64".", pid, event->seqnum);
+ log_device_debug(event->dev, "Worker ["PID_FMT"] is forked for processing SEQNUM=%"PRIu64".", worker->pidref.pid, event->seqnum);
return 0;
}
r = device_monitor_send(manager->monitor, &worker->address, event->dev);
if (r < 0) {
log_device_error_errno(event->dev, r, "Worker ["PID_FMT"] did not accept message, killing the worker: %m",
- worker->pid);
- (void) kill(worker->pid, SIGKILL);
+ worker->pidref.pid);
+ (void) pidref_kill(&worker->pidref, SIGKILL);
worker->state = WORKER_KILLED;
continue;
}
return r;
/* lookup worker who sent the signal */
- Worker *worker = hashmap_get(manager->workers, PID_TO_PTR(sender.pid));
+ Worker *worker = hashmap_get(manager->workers, &sender);
if (!worker) {
log_warning("Received notify datagram of unknown process ["PID_FMT"], ignoring.", sender.pid);
return 0;
/* Update the state of the worker. */
if (worker->state == WORKER_KILLING) {
worker->state = WORKER_KILLED;
- (void) kill(worker->pid, SIGTERM);
+ (void) pidref_kill(&worker->pidref, SIGTERM);
} else if (worker->state != WORKER_KILLED)
worker->state = WORKER_IDLE;