Skip to content

Add support for dmypy on Windows - #5859

Merged
emmatyping merged 56 commits into
python:masterfrom
emmatyping:windmypy
Nov 27, 2018
Merged

emmatyping merged 56 commits into
python:masterfrom
emmatyping:windmypy

Conversation

@emmatyping

@emmatyping emmatyping commented Oct 31, 2018 •

Copy link
Copy Markdown
Member

After a while of banging my head against the Windows APIs today, I finally have most of dmypy running on Windows (wow this makes rechecks fast!).

Here is what works and what doesn't
Everything that is publicly documented should work now:

  • dmypy start
  • dmypy stop
  • dmypy restart
  • dmypy run
  • dmypy kill
  • dmypy check
  • dmypy status

And here is a photo of it working :)
image

This depends on python/typeshed#2571. Until then selfcheck will fail (on Windows).

Closes #5019

Comment thread mypy/dmypy_server.py
@emmatyping emmatyping changed the title [WIP] Add support for dmypy on Windows Add support for dmypy on Windows Oct 31, 2018
@emmatyping emmatyping mentioned this pull request Oct 31, 2018
emmatyping added a commit that referenced this pull request Oct 31, 2018
@emmatyping

Copy link
Copy Markdown
Member Author

Okay, I tested things on 3.4 and 3.7 and it works, so this should be ready for review.

@msullivan
msullivan self-requested a review November 2, 2018 16:27

@gvanrossum gvanrossum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, I don't think I can finish this review. I hear Sully is looking at it. But I already created some comments so here they are.

Comment thread mypy/dmypy.py Outdated
Comment thread mypy/dmypy.py Outdated
Comment thread mypy/dmypy.py Outdated
@emmatyping

Copy link
Copy Markdown
Member Author

Sorry, I don't think I can finish this review.

No problem, glad to get some feedback!

@msullivan happy to talk on Friday about this if you want.

@msullivan msullivan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks so much for this!

This all looks pretty plausible, and I think I'm basically happy with the daemonizing approach, but I'm pretty nervous about the named pipe stuff. I think duplicating the serve function will lead to mistakes and bugs done the road (and the windows version getting broken), especially since we don't actually have any automated tests for this IIRC.

I see two options here:

  • Abstract out all the opening/closing/sending logic for windows and unix into a library/object with a consistent interface, so we can have a single serve routine.
  • Just totally punt on using named pipes and switch to using TCP sockets (bound to localhost). There would be some difference between setting it up for domain sockets vs TCP sockets, but most of the socket code doesn't change at all. (Or we could honestly just always use TCP sockets, even on unix.)

My inclination is that we should do the latter, unless there is a major advantage of named pipes that I'm missing?

Comment thread mypy/dmypy.py
Comment thread mypy/dmypy_server.py Outdated
@emmatyping

Copy link
Copy Markdown
Member Author

I think duplicating the serve function will lead to mistakes and bugs done the road (and the windows version getting broken)

Yeah, I can definitely understand that. The reason I chose NamedPipes was twofold: a) it is what Steve Dower recommended and b) its what mostly everyone else uses (at least from what I have seen). I am however not totally married to using them.

I see two options here
My inclination is that we should do the latter, unless there is a major advantage of named pipes that I'm missing?

Yeah, that is okay with me. I think moving entirely to TCP sockets makes the most sense, because then we can just share all IPC code across platforms, which makes the odds of things breaking very low.

@msullivan

Copy link
Copy Markdown
Collaborator

I think duplicating the serve function will lead to mistakes and bugs done the road (and the windows version getting broken)

Yeah, I can definitely understand that. The reason I chose NamedPipes was twofold: a) it is what Steve Dower recommended and b) its what mostly everyone else uses (at least from what I have seen). I am however not totally married to using them.

Yeah, in a very real sense they seem like they are the Right Thing for the job. I think the advantage of NamedPipes (and unix domain sockets) is that they have access control on them. This can matter on multi-user machines, but I think that multi-user windows dev machines aren't really a thing?

I see two options here
My inclination is that we should do the latter, unless there is a major advantage of named pipes that I'm missing?

Yeah, that is okay with me. I think moving entirely to TCP sockets makes the most sense, because then we can just share all IPC code across platforms, which makes the odds of things breaking very low.

I am somewhat inclined to keep using unix domain sockets when available, since multi-user Linux machines do still exist? It does mean some more conditional code, though I think a pretty small amount (just starting to listen and establishing the connection; all the communication should be the same).

@msullivan

Copy link
Copy Markdown
Collaborator

I am somewhat inclined to keep using unix domain sockets when available, since multi-user Linux machines do still exist? It does mean some more conditional code, though I think a pretty small amount (just starting to listen and establishing the connection; all the communication should be the same).

Though maybe this is a sign that we should stick with NamedPipe also? Though I think it does need to be abstracted out into a set of communication routines.

@emmatyping

Copy link
Copy Markdown
Member Author

Though maybe this is a sign that we should stick with NamedPipe also? Though I think it does need to be abstracted out into a set of communication routines.

I think in the interest of not making assumptions about a user's environment, erring on the side of caution makes sense here. While multi-user Windows computers are much less common, I don't think we should preclude them. Changes to the actual IPC is likely going to be pretty rare, so I think a wrapper makes the most sense. It gives the added bonus that we can change the underlying implementation later on without needing to change any of the dmypy code.

@gvanrossum

Copy link
Copy Markdown
Member

I didn't read the code, but I do agree that we should stick with unix domain sockets and named pipes, because of the access control they have. It shouldn't be hard to have a simple abstraction on top of these. (Though perhaps there might be a 3rd party package that does this?)

@msullivan msullivan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think I have now given all of the feedback I intend to.

Sorry for the slow drip, here. I spent a long time resisting the necessity of sucking it up and reading all the named pipe documentation.

Comment thread mypy/ipc.py Outdated
Comment thread mypy/ipc.py Outdated
Comment thread mypy/ipc.py Outdated
Comment thread mypy/dmypy.py Outdated
@emmatyping

Copy link
Copy Markdown
Member Author

Hm, no idea why the address would not be found in the tests, they are passing locally. I will investigate more tomorrow.

@emmatyping
emmatyping force-pushed the windmypy branch 2 times, most recently from d75c230 to e97263b Compare November 22, 2018 06:31
@emmatyping

Copy link
Copy Markdown
Member Author

I'm chasing a flake in the end-to-end daemon tests on Windows, so I will be causing a bunch of commits trying to find what is possibly a race condition, sorry!

msullivan added a commit that referenced this pull request Nov 26, 2018
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.
msullivan added a commit that referenced this pull request Nov 27, 2018
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.
@emmatyping

Copy link
Copy Markdown
Member Author

Okay, I have run @msullivan's patch to fix the race condition 9 times on Appveyor and it passed every time. So I think we are finally rid of the flake caused by the race condition 🎉

@msullivan msullivan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I have a few remaining nits, but this looks great and should be ready to land once addressed.

Thanks for all of the great work on this!

Comment thread mypy/dmypy.py Outdated
Comment thread mypy/dmypy_server.py
Comment thread mypy/ipc.py Outdated
Comment thread test-data/unit/daemon.test
Comment thread docs/source/mypy_daemon.rst
@emmatyping
emmatyping merged commit f010360 into python:master Nov 27, 2018
@emmatyping
emmatyping deleted the windmypy branch November 27, 2018 23:06
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