This partially reverts
12807b5a49d1fe60434d473afe11ff81a4c92306.
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().
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);
}
bool read_from_master:1;
bool done:1;
+ bool drain:1;
bool last_char_set:1;
char last_char;
assert(f);
+ if (f->done)
+ return true;
+
if (f->out_buffer_full > 0)
return false;
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;
}
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;
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);