// SIGWINCH Event
sd_event_source* sigwinch_event;
+ // Exit Event
+ sd_event_source* exit_event;
+
// State
enum {
PAKFIRE_PTY_STATE_INIT = 0,
pty->stdout.event = sd_event_source_unref(pty->stdout.event);
if (pty->sigwinch_event)
pty->sigwinch_event = sd_event_source_unref(pty->sigwinch_event);
+ if (pty->exit_event)
+ pty->exit_event = sd_event_source_unref(pty->exit_event);
// Close the PTY
if (pty->master.fd >= 0) {
return 0;
}
+static int pakfire_pty_drain(struct pakfire_pty* pty) {
+ // Log action
+ DEBUG(pty->ctx, "Draining requested\n");
+
+ // Update state
+ pty->state = PAKFIRE_PTY_STATE_DRAINING;
+
+ return pakfire_pty_drained(pty);
+}
+
+static int pakfire_pty_exit(sd_event_source* source, void* data) {
+ struct pakfire_pty* self = data;
+ int r;
+
+ DEBUG(self->ctx, "Exiting the PTY...\n");
+
+ // Unless we are already drained, try to drain all buffers
+ if (!pakfire_pty_drain(self)) {
+ if (!(self->master.io & PAKFIRE_PTY_HANGUP))
+ self->master.io |= PAKFIRE_PTY_READY_TO_READ | PAKFIRE_PTY_READY_TO_WRITE;
+
+ if (!(self->stdin.io & PAKFIRE_PTY_HANGUP))
+ self->stdin.io |= PAKFIRE_PTY_READY_TO_READ;
+
+ if (!(self->stdout.io & PAKFIRE_PTY_HANGUP))
+ self->stdout.io |= PAKFIRE_PTY_READY_TO_WRITE;
+
+ // Keep forwarding...
+ r = pakfire_pty_forward(self);
+ if (r < 0)
+ return r;
+ }
+
+ return pakfire_pty_done(self, 0);
+}
+
static int pakfire_pty_activity(struct pakfire_pty* pty, struct pakfire_pty_stdio* stdio, uint32_t events) {
// Do we have data to read?
if (events & (EPOLLIN|EPOLLHUP))
return -errno;
}
+ // Drain all buffers on exit
+ r = sd_event_add_exit(pty->loop, &pty->exit_event, pakfire_pty_exit, pty);
+ if (r < 0) {
+ ERROR(pty->ctx, "Could not register exit callback: %s\n", strerror(-r));
+ return r;
+ }
+
// Setup forwarding
r = pakfire_pty_setup_forwarding(pty);
if (r < 0)
return 0;
}
-int pakfire_pty_drain(struct pakfire_pty* pty) {
- pty->state = PAKFIRE_PTY_STATE_DRAINING;
-
- return pakfire_pty_drained(pty);
-}
-
/*
Creates an independent copy of the output buffer
*/