Replacing sys.stdout and sys.stderr can cause obscure crashes when trying to write non unicode data. The interpreter is terminated with SIGINT without any specific error writen on the console.
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f964820e8d0}, {0x559f50, [], SA_RESTORER, 0x7f964820e8d0}, 8) = 0 This happens easily when there is an untrapped exception which should lead to printing a traceback on stderr. To fix this, the only way is to make sure that the PYTHONIOENCODING env variable is set *before* starting the interpreter as the initialization is made very early on and the encoding cannot be set or modified after. On python 3, the default IO encoding is already properly set according to locale. Fixes: 046419a3bf8f ("pwclient: Fix encoding problems") Signed-off-by: Robin Jarry <robin.ja...@6wind.com> --- patchwork/bin/pwclient | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/patchwork/bin/pwclient b/patchwork/bin/pwclient index ed0351bf5288..7a5c32fd66eb 100755 --- a/patchwork/bin/pwclient +++ b/patchwork/bin/pwclient @@ -43,14 +43,6 @@ import re import io import locale -if sys.version_info.major == 2: - # hack to make writing unicode to standard output/error work on Python 2 - OUT_ENCODING = (sys.stdout.encoding or locale.getpreferredencoding() or - os.getenv('PYTHONIOENCODING', 'utf-8')) - sys.stdout = io.open(sys.stdout.fileno(), mode='w', - encoding=OUT_ENCODING, errors='replace') - sys.stderr = io.open(sys.stderr.fileno(), mode='w', - encoding=OUT_ENCODING, errors='replace') # Default Patchwork remote XML-RPC server URL # This script will check the PW_XMLRPC_URL environment variable @@ -821,5 +813,30 @@ def main(): sys.exit(1) +def force_io_encoding(): + """ + Force python IO (stdout/err) encoding to something else than ASCII to + support printing unicode strings. + + The only way to do it is via an environment variable *before* starting the + interpreter. + + If PYTHONIOENCODING is not set, initialize it from locale or set default + value. Then re-execute the program so that IO encoding is properly + initialized. + + The ":replace" suffix is to make python not crash on encoding errors but + replace them by printable characters. + """ + if 'PYTHONIOENCODING' in os.environ or sys.version_info.major > 2: + return + + encoding = locale.getpreferredencoding() or 'utf-8' + + os.environ['PYTHONIOENCODING'] = encoding + ':replace' + os.execvp(sys.executable, [sys.executable] + sys.argv) # no return + + if __name__ == "__main__": + force_io_encoding() main() -- 2.11.0.193.g1d1bdafd6426 _______________________________________________ Patchwork mailing list Patchwork@lists.ozlabs.org https://lists.ozlabs.org/listinfo/patchwork