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

Fixes for FreeBSD kernel #109

Merged
merged 1 commit into from Aug 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions dumb-init.c
Expand Up @@ -32,6 +32,7 @@

// Signals we care about are numbered from 1 to 31, inclusive.
// (32 and above are real-time signals.)
// TODO: this is likely not portable outside of Linux, or on strange architectures
#define MAXSIG 31

// Indices are one-indexed (signal 1 is at index 1). Index zero is unused.
Expand Down Expand Up @@ -233,12 +234,22 @@ char **parse_command(int argc, char *argv[]) {
return &argv[optind];
}

// A dummy signal handler used for signals we care about.
// On the FreeBSD kernel, ignored signals cannot be waited on by `sigwait` (but
// they can be on Linux). We must provide a dummy handler.
// https://lists.freebsd.org/pipermail/freebsd-ports/2009-October/057340.html
void dummy(int signum) {}

int main(int argc, char *argv[]) {
char **cmd = parse_command(argc, argv);
sigset_t all_signals;
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);

int i = 0;
for (i = 1; i <= MAXSIG; i++)
signal(i, dummy);

child_pid = fork();
if (child_pid < 0) {
PRINTERR("Unable to fork. Exiting.\n");
Expand Down
18 changes: 11 additions & 7 deletions testing/__init__.py
Expand Up @@ -48,13 +48,17 @@ def print_signals(args=()):

def child_pids(pid):
"""Return a list of direct child PIDs for the given PID."""
pid = str(pid)
tasks = LocalPath('/proc').join(pid, 'task').listdir()
return set(
int(child_pid)
for task in tasks
for child_pid in task.join('children').read().split()
)
children = set()
for p in LocalPath('/proc').listdir():
stat = p.join('stat')
if stat.isfile():
stat = stat.open().read()
m = re.match('^\d+ \([^\)]+\) [a-zA-Z] (\d+) ', stat)
assert m, stat
ppid = int(m.group(1))
if ppid == pid:
children.add(int(p.basename))
return children
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks worse, but turns out the children file is pretty scary:

<TheJH> ckuehl: heh, the source code for the /children file says it skips processes when dealing with a live process whose children exit while you're reading the file
<TheJH> ckuehl: because it seeks back to its last position by just skipping over N children :D
<TheJH> ckuehl: because it was written for CRIU and they never needed any stronger guarantees :D
<TheJH> ckuehl: so, uh, don't use that? :D

(thanks again @thejh!)

We don't need strong guarantees against races here since it's just a test (both the old and new code are racy). Plus, this works on non-Linux and is how pgrep -P does it.



def pid_tree(pid):
Expand Down
2 changes: 1 addition & 1 deletion tests/tty_test.py
Expand Up @@ -29,7 +29,7 @@ def readall(fd):
return result
else:
raise
if chunk == '':
if chunk == b'':
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this also explains why this test was flaky on Python 3.

return result
else:
result += chunk
Expand Down