mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
fix: correctly wait for journalctl processes to not leave zombies when streaming machine logs (#325)
* fix: call cmd.Wait() Even though the context is cancelled we still need to call cmd.Wait() after a cmd.Start() to clean up the child (reap) process. Not doing so results in a zombie journalctl. I have manually tested this, as I'm still not sure how to e2e test for this in a simple manner. Before: ``` root@uncloud2:~# ps aux|grep jou root 313 0.0 1.2 42272 23352 ? S<s Apr20 0:10 /usr/lib/systemd/systemd-journald root 15751 0.0 0.0 0 0 pts/0 Z+ 07:02 0:00 [journalctl] <defunct> root 15754 0.0 0.0 0 0 pts/0 Z+ 07:02 0:00 [journalctl] <defunct> ``` After: ``` root 313 0.0 1.2 42272 23592 ? S<s Apr20 0:10 /usr/lib/systemd/systemd-journald ``` * follow() doesnt need wait We can keep the wait function more contraint, as follow does not need it Signed-off-by: Miek Gieben <miek@miek.nl> --------- Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
@@ -31,9 +31,9 @@ const journalctl = "journalctl"
|
|||||||
|
|
||||||
var commandContext = exec.CommandContext // allow override for test
|
var commandContext = exec.CommandContext // allow override for test
|
||||||
|
|
||||||
func logs(ctx context.Context, unit string, opts api.ServiceLogsOptions) (io.ReadCloser, error) {
|
func logs(ctx context.Context, unit string, opts api.ServiceLogsOptions) (io.ReadCloser, func() error, error) {
|
||||||
if !ValidUnit(unit) {
|
if !ValidUnit(unit) {
|
||||||
return nil, fmt.Errorf("journal logs: invalid unit: %s", unit)
|
return nil, nil, fmt.Errorf("journal logs: invalid unit: %s", unit)
|
||||||
}
|
}
|
||||||
args := []string{"-u", unit, "--no-hostname"}
|
args := []string{"-u", unit, "--no-hostname"}
|
||||||
args = append(args, "-n")
|
args = append(args, "-n")
|
||||||
@@ -61,14 +61,14 @@ func logs(ctx context.Context, unit string, opts api.ServiceLogsOptions) (io.Rea
|
|||||||
cmd := commandContext(ctx, journalctl, args...)
|
cmd := commandContext(ctx, journalctl, args...)
|
||||||
p, err := cmd.StdoutPipe()
|
p, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return p, cmd.Wait, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// follow synchronously follows the io.Reader, writing each new journal entry to channel.
|
// follow synchronously follows the io.Reader, writing each new journal entry to channel.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func Logs(ctx context.Context, unit string, opts api.ServiceLogsOptions) (<-chan
|
|||||||
return nil, fmt.Errorf("journal logs: invalid unit: %s", unit)
|
return nil, fmt.Errorf("journal logs: invalid unit: %s", unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, err := logs(ctx, unit, opts)
|
reader, wait, err := logs(ctx, unit, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,7 @@ func Logs(ctx context.Context, unit string, opts api.ServiceLogsOptions) (<-chan
|
|||||||
go func() {
|
go func() {
|
||||||
defer close(outCh)
|
defer close(outCh)
|
||||||
follow(ctx, reader, outCh)
|
follow(ctx, reader, outCh)
|
||||||
|
wait()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return outCh, nil
|
return outCh, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user