unix/main: Ignore SIGPIPE signal, instead make EPIPE arrive.

Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing
to peer-closed socket will lead to sudden termination of MicroPython
process. SIGPIPE is particularly nasty, because unix shell doesn't
print anything for it, so the above looks like completely sudden and
silent termination for unknown reason. Ignoring SIGPIPE is also what
CPython does. Note that this may lead to problems using MicroPython
scripts as pipe filters, but again, that's what CPython does. So,
scripts which want to follow unix shell pipe semantics (where SIGPIPE
means "pipe was requested to terminate, it's not an error"), should
catch EPIPE themselves.
This commit is contained in:
Paul Sokolovsky 2017-05-01 18:47:26 +03:00
parent 5db55e63f3
commit 11bc21dfa8
1 changed files with 15 additions and 0 deletions

View File

@ -35,6 +35,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <signal.h>
#include "py/mpstate.h" #include "py/mpstate.h"
#include "py/nlr.h" #include "py/nlr.h"
@ -414,6 +415,20 @@ int main(int argc, char **argv) {
} }
MP_NOINLINE int main_(int argc, char **argv) { MP_NOINLINE int main_(int argc, char **argv) {
#ifdef SIGPIPE
// Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing
// to peer-closed socket will lead to sudden termination of MicroPython
// process. SIGPIPE is particularly nasty, because unix shell doesn't
// print anything for it, so the above looks like completely sudden and
// silent termination for unknown reason. Ignoring SIGPIPE is also what
// CPython does. Note that this may lead to problems using MicroPython
// scripts as pipe filters, but again, that's what CPython does. So,
// scripts which want to follow unix shell pipe semantics (where SIGPIPE
// means "pipe was requested to terminate, it's not an error"), should
// catch EPIPE themselves.
signal(SIGPIPE, SIG_IGN);
#endif
mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4)); mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4));
pre_process_options(argc, argv); pre_process_options(argc, argv);