docker-library / python

Docker Official Image packaging for Python
https://www.python.org/
MIT License
2.56k stars 1.07k forks source link

alpine: core dumped when try to run non-existing file #320

Closed GongT closed 6 years ago

GongT commented 6 years ago
docker run -it --rm python:alpine sh -c "python sssssssss.py ; echo $?"

Segmentation fault (core dumped)
139

expect:

python sssssssss.py ; echo $?

python: can't open file 'sssssssss.py': [Errno 2] No such file or directory
2


wglambert commented 6 years ago

This is the only similar issue https://github.com/docker-library/python/issues/177

The issue is alpine specific, perhaps it's an anomaly with musl.

tianon commented 6 years ago

I'm not sure what's causing it, but for someone who wants to dig into what's going on here, the end of an strace python ssssss.py has the following:

...
stat("/usr/local/lib/python3.7", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/local/lib/python3.7/lib-dynload", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/local/lib/python3.7/site-packages", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("ssssss.py", 0x7fff32d7e2f0)       = -1 ENOENT (No such file or directory)
stat("ssssss.py", 0x7fff32d7db50)       = -1 ENOENT (No such file or directory)
readlink("ssssss.py", 0x7fff32d6d570, 4096) = -1 ENOENT (No such file or directory)
open("ssssss.py", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
open("ssssss.py", O_RDONLY)             = -1 ENOENT (No such file or directory)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault

(Doesn't appear to contain any obvious clues.)

JayH5 commented 6 years ago

I've done a bit of digging. It seems that pymain->config.program is null here for some reason:

https://github.com/python/cpython/blob/1bf9cc509326bc42cd8cb1650eb9bf64550d817e/Modules/main.c#L1461-L1462

I haven't managed to figure out anything more, though. There were a bunch of changes in that file for Python 3.7 and have been a bunch since 3.7.0 was released.

Rloota commented 6 years ago

Confirming issue. Attempting to execute any non-existing file results in a segfault on fresh Alpine Python 3.6 docker image.

Elias481 commented 6 years ago

@JayH5 found reason. Investigated history and found the bug was introduced here: https://github.com/python/cpython/commit/19760863623b636a63ccf649107d9504c6465a92#diff-75445bdc3b6b3dd20b005698fa165444R2443 So it should be totally unrelated to Alpine... But on for example the stretch-slim Distro a "(null)" is returned for program name. Anyway it's a bug that has to be fixed and not "just an alpine issue"...

Bug is still present in current 3.7 branch..

tianon commented 6 years ago

So, I think this makes sense. It's the case that fprintf comes from libc -- if pymain->config.program is NULL, then it appears GLIBC handles that gracefully and %ls will give (null), where musl (arguably reasonably) segfaults when asked to format NULL as a string. See https://stackoverflow.com/a/11589479/433558 for another discussion of this same issue (where it's noted that passing NULL to %s is "undefined" according to the ANSI spec).

Has this been raised on the Python bug tracker? I imagine the patch could be as trivial as a ternary to swap out a NULL value for some other meaningful string, but I have to admit I don't understand the purpose of pymain->config.program here (given that the filename in question appears later in the error message already).

Elias481 commented 6 years ago

@tianon yes it has been raise and fixed. (see reference in timeline) I made a POC change (simply move the code that sets the config to NULL to later position). Sure it would have been possible to just swap out the NULL value, but as it alsways would show null here the better solution would have been to just remove the config.program from output.

The config.program containst the executable name for the interpreter (so python, python3.7 or whatever the binary was called). It's more nice to keep the program name in output. Even more with python as You are quite likely to have different python executables running.

Anyway stinner merged some further changes he did to this section in the master/3.8 branch to 3.7 branch and so the problem is now fixed with not a simple change but with an already existing solution.

I already tested the patched version and it puts out program name correctly and does not dump core.

tianon commented 6 years ago

Nice! So this fix will be in the next 3.7 release?

(I'm closing this issue since the issue itself is very minor, the image's behavior is an accurate representation of Python's own behavior, and it appears it'll likely be fixed in the next 3.7 release. :+1:)