mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 00:47:10 +09:00
ptyfwd,run: process remaining outputs in IO event sources
This partially reverts 12807b5a49.
Otherwise, reading or writing a fd in on_exit_event() handler may return
EBUSY, and the event loop may finish with -ELOOP.
Also, this makes drained() returns true if the PTY forwarder is already
disconnected, for safety. Hence, it is not necessary to re-introduce
pty_forward_is_done().
This commit is contained in:
@@ -1557,7 +1557,12 @@ static int run_context_reconnect(RunContext *c) {
|
||||
static void run_context_check_done(RunContext *c) {
|
||||
assert(c);
|
||||
|
||||
if (STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job)
|
||||
bool done = STRPTR_IN_SET(c->active_state, "inactive", "failed") && !c->has_job;
|
||||
|
||||
if (done && c->forward) /* If the service is gone, it's time to drain the output */
|
||||
done = pty_forward_drain(c->forward);
|
||||
|
||||
if (done)
|
||||
(void) sd_event_exit(c->event, EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ struct PTYForward {
|
||||
bool read_from_master:1;
|
||||
|
||||
bool done:1;
|
||||
bool drain:1;
|
||||
|
||||
bool last_char_set:1;
|
||||
char last_char;
|
||||
@@ -240,6 +241,9 @@ static bool drained(PTYForward *f) {
|
||||
|
||||
assert(f);
|
||||
|
||||
if (f->done)
|
||||
return true;
|
||||
|
||||
if (f->out_buffer_full > 0)
|
||||
return false;
|
||||
|
||||
@@ -759,6 +763,11 @@ static int do_shovel(PTYForward *f) {
|
||||
return pty_forward_done(f, 0);
|
||||
}
|
||||
|
||||
/* If we were asked to drain, and there's nothing more to handle from the master, then call the callback
|
||||
* too. */
|
||||
if (f->drain && drained(f))
|
||||
return pty_forward_done(f, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1086,6 +1095,20 @@ void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata
|
||||
f->userdata = userdata;
|
||||
}
|
||||
|
||||
bool pty_forward_drain(PTYForward *f) {
|
||||
assert(f);
|
||||
|
||||
/* Starts draining the forwarder. Specifically:
|
||||
*
|
||||
* - Returns true if there are no unprocessed bytes from the pty, false otherwise
|
||||
*
|
||||
* - Makes sure the handler function is called the next time the number of unprocessed bytes hits zero
|
||||
*/
|
||||
|
||||
f->drain = true;
|
||||
return drained(f);
|
||||
}
|
||||
|
||||
int pty_forward_set_priority(PTYForward *f, int64_t priority) {
|
||||
int r;
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ bool pty_forward_get_ignore_vhangup(PTYForward *f);
|
||||
|
||||
void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata);
|
||||
|
||||
bool pty_forward_drain(PTYForward *f);
|
||||
|
||||
int pty_forward_set_priority(PTYForward *f, int64_t priority);
|
||||
|
||||
int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height);
|
||||
|
||||
Reference in New Issue
Block a user