@@ -2853,6 +2853,11 @@ static void interrupt_handler(int signum) {
28532853
28542854PyOS_sighandler_t orig_interrupt_handler = NULL ;
28552855
2856+ #ifndef _WIN32
2857+ static bool s_restore_sigpipe_handler = false ;
2858+ static PyOS_sighandler_t s_orig_sigpipe_handler = SIG_DFL;
2859+ #endif
2860+
28562861PyOS_sighandler_t install_interrupt_handlers_ () {
28572862 // Installs a C handler and a Python handler
28582863 // Exported as an R symbol in case the user did some action that cleared the
@@ -3171,6 +3176,16 @@ void py_initialize(const std::string& python,
31713176 // initialize python
31723177 Py_InitializeEx (0 ); // 0 means "do not install signal handlers"
31733178 s_was_python_initialized_by_reticulate = true ;
3179+
3180+ #ifndef _WIN32
3181+ // Python ignores SIGPIPE by default to avoid the process being
3182+ // interrupted during normal pipe / IPC usage (EPIPE is handled as an
3183+ // exception instead). Because reticulate uses Py_InitializeEx(0), we
3184+ // must explicitly mirror that behavior.
3185+ s_orig_sigpipe_handler = PyOS_setsig (SIGPIPE, SIG_IGN);
3186+ s_restore_sigpipe_handler = true ;
3187+ #endif
3188+
31743189 const wchar_t *argv[1 ] = {s_python_v3.c_str ()};
31753190 PySys_SetArgv_v3 (1 , const_cast <wchar_t **>(argv));
31763191
@@ -3262,6 +3277,14 @@ void py_finalize() {
32623277 Py_MakePendingCalls ();
32633278 if (orig_interrupt_handler)
32643279 reticulate_setsig (SIGINT, orig_interrupt_handler);
3280+
3281+ #ifndef _WIN32
3282+ if (s_restore_sigpipe_handler) {
3283+ PyOS_setsig (SIGPIPE, s_orig_sigpipe_handler);
3284+ s_restore_sigpipe_handler = false ;
3285+ }
3286+ #endif
3287+
32653288 is_py_finalized = true ;
32663289 Py_Finalize ();
32673290 }
0 commit comments