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

Fix a race condition in dmypy #5956

Merged
merged 2 commits into from
Nov 27, 2018
Merged

Fix a race condition in dmypy #5956

merged 2 commits into from
Nov 27, 2018

Conversation

msullivan
Copy link
Collaborator

While thinking about what might cause flakes in #5859, I found a race
condition between dmypy stop and other dmypy commands.

dmypy stop will send a response and close the socket before the
status file has been deleted. This means that there is a window in
which the daemon has reported to a client that it has exited but while
a status file still exists. This can result in a number of issues,
including the daemon appearing to be stuck (instead of stopped) to
subsequent commands and also the exiting server deleting the status
file of a subsequently started server.

The fix is to remove the status file in cmd_stop before replying to
the request. This ensures that, as far as clients are concerned, the
daemon is exited after a stop command completes.

I tested the bug and the fix by inserting a time.sleep(1)
immediately before the sys.exit(0) in serve: this caused several
tests to fail, and the changes fixed them.

I believe that the observed flakes in the windows version in #5859
were caused by this issue, but in a way that the unix version was not
susceptible to.

While thinking about what might cause flakes in #5859, I found a race
condition between `dmypy stop` and other `dmypy` commands.

`dmypy stop` will send a response and close the socket before the
status file has been deleted. This means that there is a window in
which the daemon has reported to a client that it has exited but while
a status file still exists. This can result in a number of issues,
including the daemon appearing to be stuck (instead of stopped) to
subsequent commands and also the exiting server deleting the status
file of a subsequently started server.

The fix is to remove the status file in `cmd_stop` before replying to
the request. This ensures that, as far as clients are concerned, the
daemon is exited after a stop command completes.

I tested the bug and the fix by inserting a `time.sleep(1)`
immediately before the `sys.exit(0)` in `serve`: this caused several
tests to fail, and the changes fixed them.

I believe that the observed flakes in the windows version in #5859
were caused by this issue, but in a way that the unix version was not
susceptible to.
Copy link
Collaborator

@ethanhs ethanhs left a comment

Choose a reason for hiding this comment

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

This looks good to me! I will pull this into my Windows PR once merged. Hopefully it will end the flaking.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

LG. I wonder if the race condition is being exacerbated by the call to reset_global_state()? That seems to do a bunch of cleanup that looks pointless given that we're about to exit the process.

Two other things bug me about this code: the use of sys.exit(0) to break out of the loop (why not break?), and the two nested try/finally blocks, presumably needed to record whether the status file has been created. But I propose to clean that up later to avoid merge races for Ethan.

@@ -200,7 +201,12 @@ def serve(self) -> None:
reset_global_state()
sys.exit(0)
finally:
os.unlink(STATUS_FILE)
# If this is something other than a clean stop, remove
Copy link
Member

Choose a reason for hiding this comment

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

Maybe s/this/the final command/?

@msullivan msullivan merged commit 6402851 into master Nov 27, 2018
@msullivan msullivan deleted the dmypy-race branch November 27, 2018 01:35
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

Successfully merging this pull request may close these issues.

3 participants