Fix crashes when running spack install under nohup (#4926)

* Fix crashes when running spack install under nohup

Fixes #4919

For reasons that I do not entire understand, duplicate_stream() throws
an '[Errno 22] Invalid argument' exception when it tries to
`os.fdopen()` the duplicated file descriptor generated by
`os.dup(original.fileno())`.  See spack/llnl/util/lang.py, line
394-ish.

This happens when run under `nohup`, which supposedly has hooked
`stdin` to `/dev/null`.

It seems like opening and using `devnull` on the `input_stream` in
this situation is a reasonable way to handle the problem.

* Be more specific about error being handled.

Only catch the specific error that happens when trying to dup
the stdin that nohup provides.

Catching e as a StandardErorr and then
`type(e).__name__` tells me that it's an OSError.

Printing e.errno tells me that it's 22

Double checking tells me that 22 is EINVAL.

Phew.
This commit is contained in:
George Hartzell 2017-08-03 10:33:16 -07:00 committed by scheibelp
parent 5ac10b90c5
commit 36496b9174

View file

@ -54,6 +54,7 @@
import inspect import inspect
import multiprocessing import multiprocessing
import os import os
import errno
import shutil import shutil
import sys import sys
import traceback import traceback
@ -577,8 +578,15 @@ def child_execution(child_connection, input_stream):
parent_connection, child_connection = multiprocessing.Pipe() parent_connection, child_connection = multiprocessing.Pipe()
try: try:
# Forward sys.stdin to be able to activate / deactivate # Forward sys.stdin to be able to activate / deactivate
# verbosity pressing a key at run-time # verbosity pressing a key at run-time. When sys.stdin can't
input_stream = lang.duplicate_stream(sys.stdin) # be duplicated (e.g. running under nohup, which results in an
# '[Errno 22] Invalid argument') then just use os.devnull
try:
input_stream = lang.duplicate_stream(sys.stdin)
except OSError as e:
if e.errno == errno.EINVAL:
tty.debug("Using devnull as input_stream")
input_stream = open(os.devnull)
p = multiprocessing.Process( p = multiprocessing.Process(
target=child_execution, target=child_execution,
args=(child_connection, input_stream) args=(child_connection, input_stream)