diff options
author | Martin Pitt <martinpitt@users.noreply.github.com> | 2017-02-03 18:44:42 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-03 18:44:42 +0100 |
commit | b4a8c5ddb1326d45c0965a5d1919650d14c3c814 (patch) | |
tree | 32d86f8548dbe74b638ed73dedc10ce42127819d /src/shared | |
parent | 63927b9f4ce538cd4e730bff53fae2381df48e9e (diff) | |
parent | 95f1d6bfecde60b245fae1ab0313b550201e7880 (diff) |
Merge pull request #4973 from poettering/run-race
run: fix race for "systemd-run --wait"
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/ptyfwd.c | 30 | ||||
-rw-r--r-- | src/shared/ptyfwd.h | 2 |
2 files changed, 32 insertions, 0 deletions
diff --git a/src/shared/ptyfwd.c b/src/shared/ptyfwd.c index 293c6673fc..59b541d519 100644 --- a/src/shared/ptyfwd.c +++ b/src/shared/ptyfwd.c @@ -69,6 +69,7 @@ struct PTYForward { bool read_from_master:1; bool done:1; + bool drain:1; bool last_char_set:1; char last_char; @@ -302,6 +303,11 @@ static int shovel(PTYForward *f) { return pty_forward_done(f, 0); } + /* 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) + return pty_forward_done(f, 0); + return 0; } @@ -438,6 +444,9 @@ int pty_forward_new( r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f); if (r < 0 && r != -EPERM) return r; + + if (r >= 0) + (void) sd_event_source_set_description(f->stdin_event_source, "ptyfwd-stdin"); } r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f); @@ -446,15 +455,21 @@ int pty_forward_new( f->stdout_writable = true; else if (r < 0) return r; + else + (void) sd_event_source_set_description(f->stdout_event_source, "ptyfwd-stdout"); r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f); if (r < 0) return r; + (void) sd_event_source_set_description(f->master_event_source, "ptyfwd-master"); + r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); if (r < 0) return r; + (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); + *ret = f; f = NULL; @@ -519,3 +534,18 @@ void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata f->handler = cb; f->userdata = userdata; } + +bool pty_forward_drain(PTYForward *f) { + assert(f); + + /* Starts draining the forwarder. Specifically: + * + * - Returns true if there are no unprocessed bytes from the pty, false otherwise + * + * - Makes sure the handler function is called the next time the number of unprocessed bytes hits zero + */ + + f->drain = true; + + return f->out_buffer_full == 0 && !f->master_readable; +} diff --git a/src/shared/ptyfwd.h b/src/shared/ptyfwd.h index bd5d5fec0d..3fad1d3b26 100644 --- a/src/shared/ptyfwd.h +++ b/src/shared/ptyfwd.h @@ -51,4 +51,6 @@ bool pty_forward_is_done(PTYForward *f); void pty_forward_set_handler(PTYForward *f, PTYForwardHandler handler, void *userdata); +bool pty_forward_drain(PTYForward *f); + DEFINE_TRIVIAL_CLEANUP_FUNC(PTYForward*, pty_forward_free); |