Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kcov doesn't exit if an instrumented bash script spawns a daemon process #325

Open
dciabrin opened this issue May 6, 2020 · 2 comments
Open

Comments

@dciabrin
Copy link
Contributor

dciabrin commented May 6, 2020

I want to run kcov on bash scripts that act as agents in a cluster manager [1].
Those scripts are in charge of starting daemon services such as e.g. mysql, and
exit right after, leaving the deamon running.

When running the agent script via kcov, I noticed that kcov never returns.
This is because currently, kcov only detects the instrumented bash script exited
after all data from the pipe used as the bash xtrace fd has been read.

Unfortunately, in my case, the bash scripts forks/exec a daemon process that keeps
running in background. This means the xtrace file descriptor is leaked into this
daemon process. Consequently, the write side of the pipe is not closed when the
bash script exits, so kcov is stuck in reading and cannot detect the bash script
ended and exit successfully.

One can replicate the issue with the following bash script:

#!/bin/sh
sleep infinity &
echo main script ended

[1] https://github.com/ClusterLabs/resource-agents/ for the record

dciabrin added a commit to dciabrin/kcov that referenced this issue May 6, 2020
… to children

When bash supports xtrace fd, a new option --bash-tracefd-cloexec
uses LD_PRELOAD to configure the trace fd to not be cloneable.
This is useful when e.g. the bash script spawns a daemon process
and does not want the trace fd to leak in the daemon.
@dciabrin
Copy link
Contributor Author

dciabrin commented May 6, 2020

Some food for thought,

I couldn't find an easy way to fix this issue... I believe we want to read the trace fd until it's closed to make sure we don't lose any location info. So I assume we want to ensure the write part of the pipe can always be closed.

At some point I wondered if we should implement a strategy like "if the child process to be exec'd is not a bash script, close our the trace fd we inherited". But then, my original problem would persist if the bash agent needs to run a daemon process that is a shell script.

So I settled for a strategy like "do not clone the tracefd when forking". But as a side effect, one can't trace spawn processes if they are shell scripts. So I proposed to make that an optional behaviour.

Also, I couldn't find a simple bash-ism to configure a file descriptor with fcntl in a running script. So I had to settle for the same clever LD_PRELOAD trick that is used in option --bash-handle-sh-invocation. The drawback is that it only works for Linux. But at least getting coverage for my use case works on Linux, which looks reasonable to me.

Up for discussion, thanks!

SimonKagstrom added a commit that referenced this issue May 6, 2020
Issue #325: bash-engine: new option to not leak trace fd to children
@SimonKagstrom
Copy link
Owner

Yes, I think this sounds reasonable. Since it's an option, I think Linux-only is OK (probably 95% of the users anyway).

As an alternative, perhaps the --exit-first-process could be piggy-backed to LD_PRELOAD your new library? It might not quite describe all of your problem though, so perhaps it's best to go with a specific option.

Thanks again for the detailed descriptions and good work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants