Skip to content

Correct exitcode when running through subprocess.run #4454

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 4 commits into from
Jan 21, 2023

Conversation

moreal
Copy link
Contributor

@moreal moreal commented Jan 15, 2023

This pull request fixes exitcode of SIGINT (i.e., KeyboardInterrupt) when running through subprocess.run.

You can run the below script.

import sys, subprocess; subprocess.run([sys.executable, "-c", "raise KeyboardInterrupt"])

CPython

Python 3.10.9 (main, Dec 15 2022, 17:11:09) [Clang 14.0.0 (clang-1400.0.29.202)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys, subprocess; subprocess.run([sys.executable, "-c", "raise KeyboardInterrupt"])
Traceback (most recent call last):
  File "<string>", line 1, in <module>
KeyboardInterrupt
CompletedProcess(args=['/opt/homebrew/opt/python@3.10/bin/python3.10', '-c', 'raise KeyboardInterrupt'], returncode=-2)

Before (RustPython main)

>>>>> import sys, subprocess; subprocess.run([sys.executable, "-c", "raise KeyboardInterrupt"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
CompletedProcess(args=['/path/to/RustPython/RustPython/target/debug/rustpython', '-c', 'raise KeyboardInterrupt'], returncode=130)

After (RustPython)

Welcome to the magnificent Rust Python 0.2.0 interpreter 😱 🖖
>>>>> import sys, subprocess; subprocess.run([sys.executable, "-c", "raise KeyboardInterrupt"])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyboardInterrupt
CompletedProcess(args=['/path/to/RustPython/RustPython/target/debug/rustpython', '-c', 'raise KeyboardInterrupt'], returncode=-2)

Related links

@moreal moreal marked this pull request as draft January 15, 2023 15:41
@moreal moreal marked this pull request as ready for review January 15, 2023 15:53
@moreal
Copy link
Contributor Author

moreal commented Jan 18, 2023

I researched about failing in test_subprocess and it was because it kills the process before flushing sys.stderr and sys.stdout. I fixed it by calling interpreter::flush_std before killing process.

@moreal moreal marked this pull request as draft January 18, 2023 06:52
@moreal moreal marked this pull request as ready for review January 18, 2023 06:59
Copy link
Contributor

@fanninpm fanninpm left a comment

Choose a reason for hiding this comment

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

LGTM

Comment on lines +840 to +852
# TODO: RUSTPYTHON
if sys.platform == "win32":
windows_only_failed_tests = [
test_pymain_run_file,
test_pymain_run_file_runpy_run_module,
test_pymain_run_file_runpy_run_module_as_main,
test_pymain_run_command_run_module,
test_pymain_run_command,
test_pymain_run_module
]
for t in windows_only_failed_tests:
unittest.expectedFailure(t)

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

vm/src/vm/mod.rs Outdated
Comment on lines 771 to 786
unsafe {
if sigaction(
SIGINT,
&SigAction::new(
nix::sys::signal::SigHandler::SigDfl,
SaFlags::SA_ONSTACK,
SigSet::empty(),
),
)
.is_ok()
{
interpreter::flush_std(self);
kill(getpid(), SIGINT).expect("Expect to be killed.");
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems like a lot of unsafe.


Does Rust allow, e.g.

if (unsafe { dangerous() }) {
    // ...
}

…or is the syntax too restrictive for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't know the syntax is available. Only sigaction function needs unsafe. So I'll apply it like with cargo fmt.

Suggested change
unsafe {
if sigaction(
SIGINT,
&SigAction::new(
nix::sys::signal::SigHandler::SigDfl,
SaFlags::SA_ONSTACK,
SigSet::empty(),
),
)
.is_ok()
{
interpreter::flush_std(self);
kill(getpid(), SIGINT).expect("Expect to be killed.");
}
}
if unsafe { sigaction(
SIGINT,
&SigAction::new(
nix::sys::signal::SigHandler::SigDfl,
SaFlags::SA_ONSTACK,
SigSet::empty(),
),
) }
.is_ok()
{
interpreter::flush_std(self);
kill(getpid(), SIGINT).expect("Expect to be killed.");
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can see the change in f4a3049 commit.

Copy link
Member

@youknowone youknowone Jan 18, 2023

Choose a reason for hiding this comment

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

in general, you may want to make a new variable for complex expressions.

let action = SigAction::new(
                                nix::sys::signal::SigHandler::SigDfl,
                                SaFlags::SA_ONSTACK,
                                SigSet::empty(),
                            );
let r = unsafe { sigaction(
                            SIGINT,
                            &action,
                        ) };
if r.is_ok() {
    ...
}

Copy link
Contributor Author

@moreal moreal Jan 18, 2023

Choose a reason for hiding this comment

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

I applied it in a3507e7 commit 🙏🏻

p.s. I'm not sure why review request was removed 🤔

@moreal moreal requested review from youknowone and removed request for coolreader18 January 18, 2023 22:00
@youknowone youknowone merged commit 225efca into RustPython:main Jan 21, 2023
@youknowone
Copy link
Member

Thank you!

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