2021-01-03 21:55:15 +08:00
|
|
|
#include "process.h"
|
|
|
|
|
2021-11-12 16:49:37 +08:00
|
|
|
#include <assert.h>
|
2021-10-23 00:51:20 +08:00
|
|
|
#include <libgen.h>
|
2021-01-03 21:55:15 +08:00
|
|
|
#include "log.h"
|
|
|
|
|
2021-11-12 00:48:41 +08:00
|
|
|
enum sc_process_result
|
2021-11-20 05:42:49 +08:00
|
|
|
sc_process_execute(const char *const argv[], sc_pid *pid, unsigned flags) {
|
|
|
|
return sc_process_execute_p(argv, pid, flags, NULL, NULL, NULL);
|
2021-11-12 00:49:47 +08:00
|
|
|
}
|
|
|
|
|
2021-10-17 22:20:46 +08:00
|
|
|
ssize_t
|
2021-11-12 00:48:41 +08:00
|
|
|
sc_pipe_read_all(sc_pipe pipe, char *data, size_t len) {
|
2021-10-17 22:20:46 +08:00
|
|
|
size_t copied = 0;
|
|
|
|
while (len > 0) {
|
2021-11-12 00:48:41 +08:00
|
|
|
ssize_t r = sc_pipe_read(pipe, data, len);
|
2021-10-17 22:20:46 +08:00
|
|
|
if (r <= 0) {
|
|
|
|
return copied ? (ssize_t) copied : r;
|
|
|
|
}
|
|
|
|
len -= r;
|
|
|
|
data += r;
|
|
|
|
copied += r;
|
|
|
|
}
|
|
|
|
return copied;
|
|
|
|
}
|
2021-11-12 16:49:37 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|