Skip to content

bpo-16500: Allow registering at-fork handlers #1715

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

Merged
merged 6 commits into from
May 27, 2017
Merged

Conversation

pitrou
Copy link
Member

@pitrou pitrou commented May 22, 2017

No description provided.

@mention-bot
Copy link

@pitrou, thanks for your PR! By analyzing the history of the files in this pull request, we identified @serhiy-storchaka, @rhettinger and @tim-one to be potential reviewers.

@@ -7,10 +7,17 @@ extern "C" {

PyAPI_FUNC(int) PyOS_InterruptOccurred(void);
PyAPI_FUNC(void) PyOS_InitInterrupts(void);
PyAPI_FUNC(void) PyOS_AfterFork(void);
#ifdef HAVE_FORK
PyAPI_FUNC(void) PyOS_BeforeFork(void);
Copy link
Member Author

Choose a reason for hiding this comment

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

Question: should these functions be defined even when fork() isn't available?

Copy link
Member

Choose a reason for hiding this comment

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

They can be used only by the code that calls fork() (or similar functions).

@@ -5228,6 +5310,59 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv,
#endif /* HAVE_SPAWNV */


#ifdef HAVE_FORK
/*[clinic input]
os.register_at_fork
Copy link
Member Author

Choose a reason for hiding this comment

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

Question: should this function be defined even when fork() isn't available?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe registering fork handlers require doing other preparation work. It is easy to test if os.register_at_fork exists, and this is the only way for testing if registering the fork handlers is needed or can be just skipped (with additional preparation work).

@pitrou pitrou added the type-feature A feature request or enhancement label May 22, 2017
else if (!strcmp(when, "parent"))
lst = &interp->after_forkers_parent;
else {
PyErr_Format(PyExc_ValueError, "unexpected value for *when*: %R",
Copy link
Member

Choose a reason for hiding this comment

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

when is const char*, not PyObject*. I think you should use \"%s\" instead of %R.

It is unusual to use * for emphasizing/quoting in error 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.

Good point.

/*[clinic input]
os.register_at_fork

func: object
Copy link
Member

Choose a reason for hiding this comment

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

Do you want to support passing all arguments by keyword? In that case I prefer the name "callable" for the first parameter.

atexit.register() has different signature and allows to pass arbitrary positional and keyword arguments to the registered function.

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, perhaps only when should be keyword-enabled.

Copy link
Member

Choose a reason for hiding this comment

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

bikeshed: callable is the name of a built-in, I wouldn't use it as a parameter name. function perhaps.

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 kept func and made the first argument positional-only :-)

Copy link
Member

Choose a reason for hiding this comment

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

Victor recently changed names of parameters of C API functions to "callable", but I see that most Python functions prefer the name "func". So now I prefer this name too.

void
PyOS_BeforeFork(void)
{
/* NOTE callbacks are prepended in register_at_fork(), which is
Copy link
Member

Choose a reason for hiding this comment

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

If register_at_fork() is called in a registered function, some registered functions can be called twice.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's true. I didn't want to bother about this edge case, but a simple solution would be to copy the list before processing it.

@1st1 1st1 self-requested a review May 22, 2017 18:40
@pitrou
Copy link
Member Author

pitrou commented May 26, 2017

@1st1, were you planning to review this?

@1st1
Copy link
Member

1st1 commented May 26, 2017

@1st1, were you planning to review this?

Yes, LGTM from me. I'm going to use this API in uvloop (now I use pthread_atfork) and I wanted to make sure that my use case is covered. And it is! Thanks for working on this.

@1st1
Copy link
Member

1st1 commented May 26, 2017

My only question (that shouldn't block this PR from being merged) is can we use pthread_atfork in CPython? That would make this API work even when a C extension is calling fork directly, bypassing the CPython API.

@gpshead
Copy link
Member

gpshead commented May 26, 2017 via email

@1st1
Copy link
Member

1st1 commented May 26, 2017

Thanks, Gregory, it makes sense.

@pitrou pitrou merged commit 346cbd3 into python:master May 27, 2017
@pitrou pitrou deleted the at_fork branch May 27, 2017 15:50
ma8ma added a commit to ma8ma/cpython that referenced this pull request Jun 13, 2017
Resolve conflicts:
346cbd3 bpo-16500: Allow registering at-fork handlers (python#1715)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants