Skip to content

Commit d93c2cd

Browse files
committed
gh-152132: Fix bugs in Py_RunMain() (#153461)
* Check for signals more often. Previously, a pending exception could be removed by PyErr_Clear(). * Only call _PyInterpreterState_SetNotRunningMain() if _PyInterpreterState_SetRunningMain() has been called. * Convert _PyPathConfig_UpdateGlobal() PyStatus error to an exception.
1 parent ef5569e commit d93c2cd

1 file changed

Lines changed: 36 additions & 10 deletions

File tree

Modules/main.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ pymain_init(const _PyArgv *args)
8080

8181
/* --- pymain_run_python() ---------------------------------------- */
8282

83+
static int
84+
pymain_check_signals(void)
85+
{
86+
return Py_MakePendingCalls();
87+
}
88+
8389
/* Non-zero if filename, command (-c) or module (-m) is set
8490
on the command line */
8591
static inline int config_run_code(const PyConfig *config)
@@ -204,14 +210,18 @@ pymain_header(const PyConfig *config)
204210
static void
205211
pymain_import_readline(const PyConfig *config)
206212
{
213+
if (pymain_check_signals() < 0) {
214+
return -1;
215+
}
216+
207217
if (config->isolated) {
208-
return;
218+
return 0;
209219
}
210220
if (!config->inspect && config_run_code(config)) {
211-
return;
221+
return 0;
212222
}
213223
if (!isatty(fileno(stdin))) {
214-
return;
224+
return 0;
215225
}
216226

217227
PyObject *mod = PyImport_ImportModule("readline");
@@ -228,6 +238,7 @@ pymain_import_readline(const PyConfig *config)
228238
else {
229239
Py_DECREF(mod);
230240
}
241+
return 0;
231242
}
232243

233244

@@ -416,8 +427,7 @@ pymain_run_file_obj(PyObject *program_name, PyObject *filename,
416427
return 1;
417428
}
418429

419-
// Call pending calls like signal handlers (SIGINT)
420-
if (Py_MakePendingCalls() == -1) {
430+
if (pymain_check_signals() < 0) {
421431
fclose(fp);
422432
return pymain_exit_err_print();
423433
}
@@ -564,8 +574,7 @@ pymain_set_inspect(PyConfig *config, int inspect)
564574
static int
565575
_pymain_run_repl(PyConfig *config, int startup)
566576
{
567-
/* call pending calls like signal handlers (SIGINT) */
568-
if (Py_MakePendingCalls() == -1) {
577+
if (pymain_check_signals() < 0) {
569578
return pymain_exit_err_print();
570579
}
571580

@@ -648,13 +657,17 @@ pymain_repl(PyConfig *config, int *exitcode)
648657
static void
649658
pymain_run_python(int *exitcode)
650659
{
660+
int set_running_main = 0;
661+
651662
PyObject *main_importer_path = NULL;
652663
PyInterpreterState *interp = _PyInterpreterState_GET();
653664
/* pymain_repl() and pymain_run_stdin() modify the config */
654665
PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
655666

656667
/* ensure path config is written into global variables */
657-
if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) {
668+
PyStatus status = _PyPathConfig_UpdateGlobal(config);
669+
if (_PyStatus_EXCEPTION(status)) {
670+
_PyErr_SetFromPyStatus(status);
658671
goto error;
659672
}
660673

@@ -676,7 +689,9 @@ pymain_run_python(int *exitcode)
676689
}
677690

678691
// import readline and rlcompleter before script dir is added to sys.path
679-
pymain_import_readline(config);
692+
if (pymain_import_readline(config) < 0) {
693+
goto error;
694+
}
680695

681696
PyObject *path0 = NULL;
682697
if (main_importer_path != NULL) {
@@ -715,8 +730,13 @@ pymain_run_python(int *exitcode)
715730
pymain_header(config);
716731

717732
_PyInterpreterState_SetRunningMain(interp);
733+
set_running_main = 1;
718734
assert(!PyErr_Occurred());
719735

736+
if (pymain_check_signals() < 0) {
737+
goto error;
738+
}
739+
720740
if (config->run_command) {
721741
*exitcode = pymain_run_command(config->run_command);
722742
}
@@ -733,14 +753,20 @@ pymain_run_python(int *exitcode)
733753
*exitcode = pymain_run_stdin(config);
734754
}
735755

756+
if (pymain_check_signals() < 0) {
757+
goto error;
758+
}
759+
736760
pymain_repl(config, exitcode);
737761
goto done;
738762

739763
error:
740764
*exitcode = pymain_exit_err_print();
741765

742766
done:
743-
_PyInterpreterState_SetNotRunningMain(interp);
767+
if (set_running_main) {
768+
_PyInterpreterState_SetNotRunningMain(interp);
769+
}
744770
Py_XDECREF(main_importer_path);
745771
}
746772

0 commit comments

Comments
 (0)