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

Use os.execvp for poetry run #1236

Merged
merged 3 commits into from
Oct 4, 2019

Conversation

pbzweihander
Copy link

@pbzweihander pbzweihander commented Jul 19, 2019

  • Added tests for changed code.
  • Updated documentation for changed code.

This resolves #993.

poetry run uses subprocess.call to run the other program, making poetry spawn a new child process.
The problem is when SIGTERM is handed over; poetry does not pass it to the child process, instead terminates itself and makes zombie processes.
So I changed poetry run to use os.execvp, so poetry will replace itself with a new process and properly handle signals.

Test

I made this small script in poetry/tester.py:

import signal
import time


def handler(signum, frame):
    print(f"signal {signum} received")


def main():
    print("start")
    signal.signal(signal.SIGTERM, handler)
    time.sleep(10)
    print("end")


if __name__ == "__main__":
    main()

Then ran poetry run python poetry/tester.py and tried to kill it.

Before

$ poetry run python poetry/tester.py &
[1] 23987
start
$ ps -ax | grep tester
24270 pts/11   S      0:00 python /home/.../poetry run python poetry/tester.py
24350 pts/11   S      0:00 /home/.../python poetry/tester.py
24359 pts/11   S+     0:00 grep --color=auto tester
$ kill -TERM $!
[1]+  Terminated              poetry run python poetry/tester.py
$ ps -ax | grep tester
24350 pts/11   S      0:00 /home/.../python poetry/tester.py
24446 pts/11   S+     0:00 grep --color=auto tester
$ 
end

Fixed

$ python -m poetry run python poetry/tester.py &
[1] 25282
start
$ ps -ax | grep tester
25282 pts/11   S      0:00 /home/.../python poetry/tester.py
25364 pts/11   S+     0:00 grep --color=auto tester
$ kill -TERM $!
signal 15 received
$ 
end
[1]+  Done                    python -m poetry run python poetry/tester.py

Test - scripts feature

I added the following lines to pyprojects.toml.

...
[tools.poetry.scripts]
...
tester = "poetry.tester:main"

Then ran poetry run tester and tried to kill it.

Before

$ poetry run tester &
[1] 27077
start
$ ps -ax | grep tester
27077 pts/11   S      0:00 python /home/.../poetry run tester
27173 pts/11   S      0:00 /home/.../python -c import sys; from importlib import import_module; sys.argv = ['tester']; import_module('poetry.tester').main()
27189 pts/11   S+     0:00 grep --color=auto tester
$ kill -TERM $!
[1]+  Terminated              poetry run tester
$ ps -ax | grep tester
27173 pts/11   S      0:00 /home/.../python -c import sys; from importlib import import_module; sys.argv = ['tester']; import_module('poetry.tester').main()
27266 pts/11   S+     0:00 grep --color=auto tester
$ 
end

Fixed

$ python -m poetry run tester &
[1] 27996
start
$ ps -ax | grep tester
27996 pts/11   S      0:00 /home/.../python -c import sys; from importlib import import_module; sys.argv = ['tester']; import_module('poetry.tester').main()
28082 pts/11   S+     0:00 grep --color=auto tester
$ kill -TERM $!
signal 15 received
$ 
end
[1]+  Done                    python -m poetry run tester

@digitalresistor
Copy link
Contributor

👍 on this however using os.execvp does not work on Windows. Please take a look at and steal (my permission is hereby given to relicense it under whatever Poetry is licensed as) my code from here: https://github.com/bertjwregeer/vrun/tree/master/src/vrun which supports both Unix and Windows.

@digitalresistor
Copy link
Contributor

specifically you want this file: https://github.com/bertjwregeer/vrun/blob/master/src/vrun/oscompat.py

@simnalamburt
Copy link

The document says that os.execvp is available in Windows. May I ask what exception is thrown when we try to use os.execvp in Windows?

스크린샷 2019-07-24 오후 2 57 00

https://docs.python.org/3/library/os.html#os.execvp

@pbzweihander
Copy link
Author

I found in Windows, exec does not actually replace current process and instead creates a new one and exits the current one.

So I think poetry needs to create a new process and wait until the new one exits. (https://github.com/bertjwregeer/vrun/blob/a726be8106a00621361f60079ac403e5bc16864a/src/vrun/oscompat.py#L34)

@digitalresistor
Copy link
Contributor

If you try to use the exec calls on Windows you get into a really weird state where the process you are running can't be controlled from the cmd.exe window it is spawned from.

You need to do the whole popen dance so that you can send key strokes from the foreground to the process that was spawned on Windows.

@digitalresistor
Copy link
Contributor

I see that @pbzweihander got there before me! :-D

Please steal my code, I didn't come to that conclusion the easy way!

@simnalamburt
Copy link

Now I think this PR is ready to be merged since I see no more blockers.

@brycedrennan
Copy link
Contributor

Thanks for your contribution. I'm not sure when someone will have a chance to dig into this.

I imagine its pretty hard to add an automated test for this?

@brycedrennan brycedrennan added the kind/feature Feature requests/implementations label Aug 16, 2019
@digitalresistor
Copy link
Contributor

What kind of tests are you looking for?

@sdispater sdispater mentioned this pull request Oct 4, 2019
2 tasks
@maksbotan
Copy link
Contributor

@sdispater so, are there plans to merge this one? :)

@sdispater sdispater changed the base branch from develop to master October 4, 2019 13:33
@sdispater sdispater merged commit a581ff6 into python-poetry:master Oct 4, 2019
@sdispater
Copy link
Member

Thanks a lot for this PR!

@pbzweihander pbzweihander deleted the use-execvp-for-run branch October 4, 2019 15:34
michielboekhoff pushed a commit to michielboekhoff/poetry that referenced this pull request Oct 29, 2019
* Use os.execvp for poetry run

* Use subprocess.Popen for Windows

* Handle env kwargs
michielboekhoff pushed a commit to michielboekhoff/poetry that referenced this pull request Oct 29, 2019
* Use os.execvp for poetry run

* Use subprocess.Popen for Windows

* Handle env kwargs
@rpdelaney
Copy link
Contributor

Does this have any effect on performance?

@simnalamburt
Copy link

It'll boost performance since os.execvp is faster than subprocess.call

@akdor1154
Copy link

I think this broke calling scripts on Windows - if I do poetry run script.py it used to get called as subprocess.call(script.py, shell=True) but now gets called as Popen([script.py]) This doesn't work, see https://stackoverflow.com/questions/912830/using-subprocess-to-run-python-script-on-windows.

@simnalamburt
Copy link

It’s actually calling Popen([‘python3.exe’, blabla]) which seems OK according to your link https://stackoverflow.com/a/912847

@benjirewis
Copy link

I've noticed killing poetry processes with SIGTERM creates a status code of 143. While that error code does indicate graceful termination after receiving SIGTERM, why not just return 0?

Copy link

github-actions bot commented Mar 3, 2024

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
kind/feature Feature requests/implementations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

poetry run should use execve syscall
9 participants