public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH] ignore HUP before client connect on pty
@ 2026-04-22  8:52 Dominik Csapak
  2026-04-22  8:55 ` Dominik Csapak
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Dominik Csapak @ 2026-04-22  8:52 UTC (permalink / raw)
  To: pve-devel

Since debian trixie, the `login` tool timing changed and it always sends
a HUP first thing. This caused spiceterm to immediately close again.

To fix that, ignore all HUPs on the PTY side until at least one client
is connected.

To achieve that the client count is moved inside the SpiceScreen struct,
since that is reachable from all callbacks needed
(connect/disconnect/timeout/channel watcher).

The only potential downside is if the cmd really exits before a client
connects, it blocks the client for a bit without any indication as to
why and then disconnects. Tested that by replacing `login` with
`/bin/false` and the client disconnected after a few seconds
automatically.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
i opted to not use the same workaround as in termproxy (which ignores
all HUPs on the pty side) since it should be enough to only do that
until the client is connected. All HUPs afterwards normally closes
the terminal.

 src/screen.c    | 18 +++++++++---------
 src/spiceterm.c | 19 ++++++++++++++++++-
 src/spiceterm.h |  2 ++
 3 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/screen.c b/src/screen.c
index c5247a8..267fe98 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -568,26 +568,24 @@ static void set_client_capabilities(QXLInstance *qin, uint8_t client_present, ui
     }
 }
 
-static int client_count = 0;
-
 static void client_connected(SpiceScreen *spice_screen) {
-    client_count++;
+    spice_screen->client_count++;
 
-    DPRINTF(1, "client_count = %d", client_count);
+    DPRINTF(1, "client_count = %d", spice_screen->client_count);
 }
 
 static void client_disconnected(SpiceScreen *spice_screen) {
-    if (client_count > 0) {
-        client_count--;
-        DPRINTF(1, "client_count = %d", client_count);
+    if (spice_screen->client_count > 0) {
+        spice_screen->client_count--;
+        DPRINTF(1, "client_count = %d", spice_screen->client_count);
         exit(0); // fixme: cleanup?
     }
 }
 
 static void do_conn_timeout(void *opaque) {
-    // SpiceScreen *spice_screen = opaque;
+    SpiceScreen *spice_screen = opaque;
 
-    if (client_count <= 0) {
+    if (spice_screen->client_count <= 0) {
         printf("connection timeout - stopping server\n");
         exit(0); // fixme: cleanup?
     }
@@ -664,6 +662,8 @@ SpiceScreen *spice_screen_new(
     spice_screen->width = width;
     spice_screen->height = height;
 
+    spice_screen->client_count = 0;
+
     g_cond_init(&spice_screen->command_cond);
     g_mutex_init(&spice_screen->command_mutex);
 
diff --git a/src/spiceterm.c b/src/spiceterm.c
index 77d2d05..b5259e7 100644
--- a/src/spiceterm.c
+++ b/src/spiceterm.c
@@ -1549,6 +1549,22 @@ static gboolean master_error_callback(GIOChannel *channel, GIOCondition conditio
     return FALSE;
 }
 
+static gboolean master_hup_callback(GIOChannel *channel, GIOCondition condition, gpointer data) {
+    spiceTerm *vt = (spiceTerm *)data;
+
+    DPRINTF(1, "condition %d", condition);
+
+    // /usr/bin/login sends a HUP at the beginning, meaning we must ignore them
+    // until we had at least one client, otherwise we exit immediately.
+    if (vt->screen->client_count < 1) {
+        return TRUE;
+    }
+
+    exit(0);
+
+    return FALSE;
+}
+
 static void master_watch(int master, int event, void *opaque) {
     spiceTerm *vt = (spiceTerm *)opaque;
     int c;
@@ -1717,7 +1733,8 @@ int main(int argc, char **argv) {
     GIOChannel *channel = g_io_channel_unix_new(master);
     g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
     g_io_channel_set_encoding(channel, NULL, NULL);
-    g_io_add_watch(channel, G_IO_ERR | G_IO_HUP, master_error_callback, vt);
+    g_io_add_watch(channel, G_IO_ERR, master_error_callback, vt);
+    g_io_add_watch(channel, G_IO_HUP, master_hup_callback, vt);
 
     vt->screen->mwatch = vt->screen->core->watch_add(
         master, SPICE_WATCH_EVENT_READ /* |SPICE_WATCH_EVENT_WRITE */, master_watch, vt
diff --git a/src/spiceterm.h b/src/spiceterm.h
index 9083c4a..9c189e0 100644
--- a/src/spiceterm.h
+++ b/src/spiceterm.h
@@ -50,6 +50,8 @@ struct SpiceScreen {
     int primary_height;
     int primary_width;
 
+    int client_count;
+
     SpiceTimer *conn_timeout_timer;
     SpiceWatch *mwatch; /* watch master pty */
 
-- 
2.47.3





^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-04-22 10:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-04-22  8:52 [PATCH] ignore HUP before client connect on pty Dominik Csapak
2026-04-22  8:55 ` Dominik Csapak
2026-04-22 10:03 ` Fiona Ebner
2026-04-22 10:36 ` applied: " Thomas Lamprecht

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal