diff options
Diffstat (limited to 'src/shared/ptyfwd.c')
-rw-r--r-- | src/shared/ptyfwd.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 0c92184ba5..94a4dd513f 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -170,6 +171,30 @@ static bool ignore_vhangup(PTYForward *f) { return false; } +static bool drained(PTYForward *f) { + int q = 0; + + assert(f); + + if (f->out_buffer_full > 0) + return false; + + if (f->master_readable) + return false; + + if (ioctl(f->master, TIOCINQ, &q) < 0) + log_debug_errno(errno, "TIOCINQ failed on master: %m"); + else if (q > 0) + return false; + + if (ioctl(f->master, TIOCOUTQ, &q) < 0) + log_debug_errno(errno, "TIOCOUTQ failed on master: %m"); + else if (q > 0) + return false; + + return true; +} + static int shovel(PTYForward *f) { ssize_t k; @@ -305,7 +330,7 @@ static int shovel(PTYForward *f) { /* If we were asked to drain, and there's nothing more to handle from the master, then call the callback * too. */ - if (f->drain && f->out_buffer_full == 0 && !f->master_readable) + if (f->drain && drained(f)) return pty_forward_done(f, 0); return 0; @@ -546,6 +571,28 @@ bool pty_forward_drain(PTYForward *f) { */ f->drain = true; + return drained(f); +} + +int pty_forward_set_priority(PTYForward *f, int64_t priority) { + int r; + assert(f); - return f->out_buffer_full == 0 && !f->master_readable; + r = sd_event_source_set_priority(f->stdin_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->stdout_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->master_event_source, priority); + if (r < 0) + return r; + + r = sd_event_source_set_priority(f->sigwinch_event_source, priority); + if (r < 0) + return r; + + return 0; } |