From 978ada48c924f51580338940fe1aa2420befcea8 Mon Sep 17 00:00:00 2001 From: Ryan Petrello Date: Mon, 2 Jul 2018 18:35:35 -0400 Subject: [PATCH] improve error handling robustness for os.execvpe see: https://github.com/pexpect/pexpect/issues/512 --- ptyprocess/ptyprocess.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ptyprocess/ptyprocess.py b/ptyprocess/ptyprocess.py index 78d19fd..7ae4308 100644 --- a/ptyprocess/ptyprocess.py +++ b/ptyprocess/ptyprocess.py @@ -206,6 +206,18 @@ def spawn( if not isinstance(argv, (list, tuple)): raise TypeError("Expected a list or tuple for argv, got %r" % argv) + # env vars must be utf-8 encoded strings + # https://github.com/pexpect/pexpect/issues/512 + # + # from https://docs.python.org/3.8/library/os.html#os.execvpe + # Errors will be reported as OSError exceptions. + _text_type = str + if not PY3: + _text_type = unicode + for k, v in env.items(): + if isinstance(v, _text_type): + env[k] = v.encode('utf-8') + # Shallow copy of argv so we can modify it argv = argv[:] command = argv[0] @@ -289,10 +301,14 @@ def spawn( os.execv(command, argv) else: os.execvpe(command, argv, env) - except OSError as err: + except Exception as err: # [issue #119] 5. If exec fails, the child writes the error # code back to the parent using the pipe, then exits. - tosend = 'OSError:{}:{}'.format(err.errno, str(err)) + if isinstance(err, OSError): + tosend = 'OSError:{}:{}'.format(err.errno, str(err)) + else: + cls_name = err.__class__.__name__ + tosend = 'Exception:0:{}: {}'.format(cls_name, str(err)) if PY3: tosend = tosend.encode('utf-8') os.write(exec_err_pipe_write, tosend)