]> git.ipfire.org Git - pakfire.git/commitdiff
pty: Disconnect as early as possible
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 13:54:25 +0000 (13:54 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 6 Oct 2024 13:54:25 +0000 (13:54 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/pty.c

index 047477a5f6026910537cdafcb339ded779488cd0..4c09fc4d119a4d98f16b6f5238bcb506e469e836 100644 (file)
@@ -90,6 +90,62 @@ struct pakfire_pty {
        } state;
 };
 
+static int pakfire_pty_restore_attrs(struct pakfire_pty* pty,
+               struct pakfire_pty_stdio* stdio) {
+       int r;
+
+       // Skip everything if fd is not a TTY
+       if (!isatty(stdio->fd))
+               return 0;
+
+       // Restore the flags
+       r = fcntl(stdio->fd, F_SETFL, stdio->flags);
+       if (r < 0) {
+               CTX_ERROR(pty->ctx, "Could not set flags for file descriptor %d: %s\n",
+                       stdio->fd, strerror(errno));
+               return -errno;
+       }
+
+       // Restore the attributes
+       r = tcsetattr(stdio->fd, TCSANOW, &stdio->attrs);
+       if (r) {
+               CTX_ERROR(pty->ctx, "Could not restore terminal attributes for %d, ignoring: %s\n",
+                       stdio->fd, strerror(errno));
+               return -errno;
+       }
+
+       // Close the file descriptor
+       close(stdio->fd);
+       stdio->fd = -1;
+
+       return 0;
+}
+
+static int pakfire_pty_disconnect(struct pakfire_pty* pty) {
+       if (pty->master.fd >= 0) {
+               close(pty->master.fd);
+               pty->master.fd = 1;
+       }
+
+       // Restore any changed terminal attributes
+       if (pty->stdin.fd >= 0)
+               pakfire_pty_restore_attrs(pty, &pty->stdin);
+       if (pty->stdout.fd >= 0)
+               pakfire_pty_restore_attrs(pty, &pty->stdout);
+
+       // Clear events
+       if (pty->master.event)
+               pty->master.event = sd_event_source_unref(pty->master.event);
+       if (pty->stdin.event)
+               pty->stdin.event = sd_event_source_unref(pty->stdin.event);
+       if (pty->stdout.event)
+               pty->stdout.event = sd_event_source_unref(pty->stdout.event);
+       if (pty->sigwinch_event)
+               pty->sigwinch_event = sd_event_source_unref(pty->sigwinch_event);
+
+       return 0;
+}
+
 static int pakfire_pty_drained(struct pakfire_pty* pty) {
        int q;
        int r;
@@ -133,6 +189,9 @@ static int pakfire_pty_done(struct pakfire_pty* pty, int code) {
        if (pty->state == PAKFIRE_PTY_STATE_DONE)
                return 0;
 
+       // Disconnect
+       pakfire_pty_disconnect(pty);
+
        // Fetch a reference to the event loop
        loop = sd_event_ref(pty->loop);
 
@@ -293,37 +352,6 @@ static int pakfire_pty_forward(struct pakfire_pty* pty) {
        return 0;
 }
 
-static int pakfire_pty_restore_attrs(struct pakfire_pty* pty,
-               const struct pakfire_pty_stdio* stdio) {
-       int r;
-
-       // Skip if we don't know the file descriptor
-       if (stdio->fd < 0)
-               return 0;
-
-       // Skip everything if fd is not a TTY
-       if (!isatty(stdio->fd))
-               return 0;
-
-       // Restore the flags
-       r = fcntl(stdio->fd, F_SETFL, stdio->flags);
-       if (r < 0) {
-               CTX_ERROR(pty->ctx, "Could not set flags for file descriptor %d: %s\n",
-                       stdio->fd, strerror(errno));
-               return -errno;
-       }
-
-       // Restore the attributes
-       r = tcsetattr(stdio->fd, TCSANOW, &stdio->attrs);
-       if (r) {
-               CTX_ERROR(pty->ctx, "Could not restore terminal attributes for %d, ignoring: %s\n",
-                       stdio->fd, strerror(errno));
-               return -errno;
-       }
-
-       return 0;
-}
-
 /*
        Forwards any window size changes.
 */
@@ -611,25 +639,13 @@ static int pakfire_pty_setup(sd_event_source* source, int fd, uint32_t events, v
 }
 
 static void pakfire_pty_free(struct pakfire_pty* pty) {
-       // Restore any changed terminal attributes
-       if (pty->stdin.fd >= 0)
-               pakfire_pty_restore_attrs(pty, &pty->stdin);
-       if (pty->stdout.fd >= 0)
-               pakfire_pty_restore_attrs(pty, &pty->stdout);
-       if (pty->master.event)
-               sd_event_source_unref(pty->master.event);
-       if (pty->stdin.event)
-               sd_event_source_unref(pty->stdin.event);
-       if (pty->stdout.event)
-               sd_event_source_unref(pty->stdout.event);
-       if (pty->sigwinch_event)
-               sd_event_source_unref(pty->sigwinch_event);
+       pakfire_pty_disconnect(pty);
+
        if (pty->socket[0] >= 0)
                close(pty->socket[0]);
        if (pty->socket[1] >= 0)
                close(pty->socket[1]);
-       if (pty->master.fd >= 0)
-               close(pty->master.fd);
+
        if (pty->loop)
                sd_event_unref(pty->loop);
        if (pty->ctx)