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

Add fork_func #487

Merged
merged 4 commits into from
Jan 14, 2024
Merged

Add fork_func #487

merged 4 commits into from
Jan 14, 2024

Conversation

gperciva
Copy link
Member

No description provided.

@gperciva gperciva closed this Jun 26, 2023
@gperciva gperciva reopened this Jun 27, 2023
@gperciva gperciva closed this Jun 27, 2023
@gperciva gperciva reopened this Jun 27, 2023
@gperciva gperciva marked this pull request as draft June 27, 2023 21:22
@gperciva gperciva force-pushed the fork-func branch 4 times, most recently from e9ba002 to 9dfd1de Compare June 28, 2023 16:59
@gperciva gperciva marked this pull request as ready for review June 28, 2023 17:02
@gperciva
Copy link
Member Author

There's more overhead in fork_func(); fork_func_wait(); than in pthread, but it's less than 1ms, and more importantly, there isn't a lot of variability.

Tests when waiting for 0ms, 1ms, 30ms, and 90ms on FreeBSD 12.4 with kern.timecounter.alloweddeviation=0:

0ms
1ms
30ms
90ms

@gperciva
Copy link
Member Author

This PR includes #488.

@gperciva gperciva marked this pull request as draft June 28, 2023 18:28
@gperciva gperciva force-pushed the fork-func branch 2 times, most recently from 295e2de to 04a8cb3 Compare June 28, 2023 18:36
@gperciva
Copy link
Member Author

Having a separate file check_exit.c seems like overkill. However, I wanted to have check_perftest.c and check_order.c in separate files. Once that was done, I could either have the separate check_exit.c, or add a check.c which only contained the exit-checking-related functions.

@gperciva
Copy link
Member Author

Testing with valgrind on macOS does require the sleep-sort values to be separated by more than 100ms. Empirically, when tested with 300ms and 400ms, the order was sometimes reversed (1 out of 2 attempts; I didn't try more tests to get a statistical estimate).

I went with 200ms, because occasionally-failing tests are really annoying.

{
pid_t pid;

/* Fork */
Copy link
Member

Choose a reason for hiding this comment

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

This is traditionally written with switch (pid = fork()), see fork(2) for example.

Copy link
Member Author

Choose a reason for hiding this comment

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

sigh, ok, I'll change it. I still think it's easier to leverage our normal "do something; did it fail?" idiom. Then if it did not fail, then figure out what type of success it had.

BTW, although I've seen the traditional switch method before, it's not in the freebsd 12.4 man page, which has no EXAMPLES section:
https://man.freebsd.org/cgi/man.cgi?query=fork&apropos=0&sektion=2&manpath=FreeBSD+12.4-RELEASE

Evidently that was only added in 13.1:
https://reviews.freebsd.org/D27626

util/fork_func.c Outdated
warn0("pid %jd: stopped with %i",
(intmax_t)pid, WSTOPSIG(status));
else
warn0("pid %jd: stopped for unknown reason.");
Copy link
Member

Choose a reason for hiding this comment

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

Is "stopped" what you want here? I mean, stopped != exited.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch, changed.

@gperciva gperciva force-pushed the fork-func branch 2 times, most recently from ece2651 to 469d76f Compare August 27, 2023 17:00
@gperciva
Copy link
Member Author

Updated with a REBASE commit.

I also rebased onto master, to clear up the git conflict.


(void)cookie; /* UNUSED */

if (execlp("true", "", NULL))
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason you want to invoke true(1) with an argv0 of ""?

Copy link
Member Author

Choose a reason for hiding this comment

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

nope, fixed.

static int
func_exit(void * cookie)
{
int exitcode = *((int *)cookie);
Copy link
Member

Choose a reason for hiding this comment

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

I would write this as

int *exitcodep = (int *)cookie;

return (*exitcodep);

Does the same thing, but we generally follow a convention of "pointer = cookie" at the start of callback functions.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed.

util/fork_func.c Outdated
if (WIFSIGNALED(status))
warn0("pid %jd: signalled with %i",
(intmax_t)pid, WTERMSIG(status));
else if (WIFSTOPPED(status))
Copy link
Member

Choose a reason for hiding this comment

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

Do we care about reporting processes which were stopped but not terminated?

Copy link
Member Author

Choose a reason for hiding this comment

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

I figured that anything other than WIFEXITED was unusual and worth reporting?

I mean, the overall point of fork_func_wait() is "wait until the forked process is finished". I don't have a good sense of what to do if there's an error, so I figured that reporting it was a decent lower bound?

Copy link
Member

Choose a reason for hiding this comment

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

     WIFSTOPPED(status)
             True if the process has not terminated, but has stopped and can
             be restarted.  This macro can be true only if the wait call
             specified the WUNTRACED option or if the child process is being
             traced (see ptrace(2)).

Since we're not passing the WUNTRACED flag (or any flags at all for that matter), the only thing this would report to us is if the process is being traced... in which case the signal value isn't particularly useful anyway. So I would just handle this with the 'unknown reason' message.

Copy link
Member Author

Choose a reason for hiding this comment

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

ok, removed

util/fork_func.c Outdated
goto err0;
case 0:
/* In child process: Run the provided function, then exit. */
_exit((*func)(cookie));
Copy link
Member

Choose a reason for hiding this comment

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

We generally omit the * when calling via a function pointer. (The C standard says it's optional.)

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

util/fork_func.c Outdated
@@ -12,7 +12,7 @@
* Fork and run ${func} in a new process, with ${cookie} as the sole argument.
*/
pid_t
fork_func(int (* func)(void *), void * cookie)
fork_func(int (*func)(void *), void * cookie)
Copy link
Member Author

Choose a reason for hiding this comment

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

wait, now I'm rethinking this one.

in events/*.c, there's 6 function pointers defined as (*func) with no spaces. There's only 2 instances of (* func), both of which in cpusupport code I wrote.

OTOH, when I grep for (* , there's 56 hits, and at first glance, at least 90% of them are function pointers.

So I'm guessing that the desired style is:

int
foo(int (* func)(void *))

?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, our STYLE says "space between * and variable name". Applies to function pointers just as much as any other pointers.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed the bad commit, and made a separate PR for fixing the style of our function pointers.

@gperciva
Copy link
Member Author

I rebased the existing REBASE commits, but then added one more small change.

/* Fork */
switch (pid = fork()) {
case -1:
warnp("fork");
Copy link
Member

Choose a reason for hiding this comment

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

For consistency with the other cases, I would add /* Error in fork system call. */

util/fork_func.c Outdated
} else {
/* Child ${pid} did not exit cleanly. */

/* Warn about the reason for the unclean exit. */
Copy link
Member

Choose a reason for hiding this comment

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

Combine these into a single (multi-line) comment.

util/fork_func.c Outdated

/* Warn about the reason for the unclean exit. */
if (WIFSIGNALED(status))
warn0("pid %jd: signalled with %i",
Copy link
Member

Choose a reason for hiding this comment

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

Maybe "terminated by signal" would be clearer?

Also, any reason you used %i instead of the more common %d?

Copy link
Member Author

Choose a reason for hiding this comment

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

Hold-over from when I was a TA: "use %i for integer, and %f for float". (Because to a first-year engineering student, "decimal" means something like "1.23".)

Ok, I'll switch to %d.

@cperciva
Copy link
Member

A few minor nits but generally looks good. Feel free to make changes and rebase unless there's something you're not sure about.

@gperciva gperciva marked this pull request as ready for review January 14, 2024 02:17
@gperciva
Copy link
Member Author

Fixes made, rebased, ready for merge.

@cperciva cperciva merged commit 4b2eb56 into master Jan 14, 2024
2 checks passed
@gperciva gperciva deleted the fork-func branch January 14, 2024 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants