Introduce process observer
Add a tool to easily observe process termination. This allows to move this complexity out of the server code.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "process.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <libgen.h>
|
||||
#include "log.h"
|
||||
|
||||
@@ -41,3 +42,80 @@ sc_pipe_read_all(sc_pipe pipe, char *data, size_t len) {
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
static int
|
||||
run_observer(void *data) {
|
||||
struct sc_process_observer *observer = data;
|
||||
sc_process_wait(observer->pid, false); // ignore exit code
|
||||
|
||||
sc_mutex_lock(&observer->mutex);
|
||||
observer->terminated = true;
|
||||
sc_cond_signal(&observer->cond_terminated);
|
||||
sc_mutex_unlock(&observer->mutex);
|
||||
|
||||
if (observer->listener) {
|
||||
observer->listener->on_terminated(observer->listener_userdata);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_process_observer_init(struct sc_process_observer *observer, sc_pid pid,
|
||||
const struct sc_process_listener *listener,
|
||||
void *listener_userdata) {
|
||||
// Either no listener, or on_terminated() is defined
|
||||
assert(!listener || listener->on_terminated);
|
||||
|
||||
bool ok = sc_mutex_init(&observer->mutex);
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ok = sc_cond_init(&observer->cond_terminated);
|
||||
if (!ok) {
|
||||
sc_mutex_destroy(&observer->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
observer->pid = pid;
|
||||
observer->listener = listener;
|
||||
observer->listener_userdata = listener_userdata;
|
||||
observer->terminated = false;
|
||||
|
||||
ok = sc_thread_create(&observer->thread, run_observer, "process_observer",
|
||||
observer);
|
||||
if (!ok) {
|
||||
sc_cond_destroy(&observer->cond_terminated);
|
||||
sc_mutex_destroy(&observer->mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
sc_process_observer_timedwait(struct sc_process_observer *observer,
|
||||
sc_tick deadline) {
|
||||
sc_mutex_lock(&observer->mutex);
|
||||
bool timed_out = false;
|
||||
while (!observer->terminated && !timed_out) {
|
||||
timed_out = !sc_cond_timedwait(&observer->cond_terminated,
|
||||
&observer->mutex, deadline);
|
||||
}
|
||||
bool terminated = observer->terminated;
|
||||
sc_mutex_unlock(&observer->mutex);
|
||||
|
||||
return terminated;
|
||||
}
|
||||
|
||||
void
|
||||
sc_process_observer_join(struct sc_process_observer *observer) {
|
||||
sc_thread_join(&observer->thread, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sc_process_observer_destroy(struct sc_process_observer *observer) {
|
||||
sc_cond_destroy(&observer->cond_terminated);
|
||||
sc_mutex_destroy(&observer->mutex);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user