From: Yu Watanabe Date: Mon, 28 Jul 2025 15:47:45 +0000 (+0900) Subject: ptyfwd: do not try to read master if already disconnected X-Git-Tag: v258-rc2~38^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=446431f5c9f098d86709abfec79a2360856510e4;p=thirdparty%2Fsystemd.git ptyfwd: do not try to read master if already disconnected When PTYForward.done is set, the PTYForward.master is already disconnected. Let's not try to read the already closed file descriptor. Also, if we previously received vhangup, then it is not necessary to re-read the device to check vhangup, as we already know. This also make the check slightly delayed, and use a defer event source, to make the function can be called safely in another event source. --- diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 543466ceb73..bc312f17019 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -60,6 +60,7 @@ struct PTYForward { sd_event_source *master_event_source; sd_event_source *sigwinch_event_source; sd_event_source *exit_event_source; + sd_event_source *defer_event_source; struct termios saved_stdin_attr; struct termios saved_stdout_attr; @@ -122,6 +123,7 @@ static void pty_forward_disconnect(PTYForward *f) { f->master_event_source = sd_event_source_unref(f->master_event_source); f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); f->exit_event_source = sd_event_source_unref(f->exit_event_source); + f->defer_event_source = sd_event_source_unref(f->defer_event_source); f->event = sd_event_unref(f->event); if (f->output_fd >= 0) { @@ -892,6 +894,23 @@ static int on_exit_event(sd_event_source *e, void *userdata) { return pty_forward_done(f, 0); } +static int on_defer_event(sd_event_source *s, void *userdata) { + PTYForward *f = ASSERT_PTR(userdata); + return shovel_force(f); +} + +static int pty_forward_add_defer(PTYForward *f) { + assert(f); + + if (f->done) + return 0; + + if (f->defer_event_source) + return sd_event_source_set_enabled(f->defer_event_source, SD_EVENT_ONESHOT); + + return sd_event_add_defer(f->event, &f->defer_event_source, on_defer_event, f); +} + int pty_forward_new( sd_event *event, int master, @@ -1083,9 +1102,11 @@ int pty_forward_honor_vhangup(PTYForward *f) { f->flags &= ~(PTY_FORWARD_IGNORE_VHANGUP | PTY_FORWARD_IGNORE_INITIAL_VHANGUP); - /* We shall now react to vhangup()s? Let's check immediately if we might be in one. */ - f->master_readable = true; - return shovel(f); + if (f->master_hangup) + return 0; + + /* We shall now react to vhangup()s? Let's check if we might be in one. */ + return pty_forward_add_defer(f); } bool pty_forward_vhangup_honored(const PTYForward *f) {