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:
Yu Watanabe
2024-12-25 17:40:04 +09:00
parent bb4244f454
commit 7647378b74
3 changed files with 31 additions and 1 deletions

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);