• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Python interpreter main program */
2 
3 #include "Python.h"
4 #include "pycore_call.h"          // _PyObject_CallNoArgs()
5 #include "pycore_initconfig.h"    // _PyArgv
6 #include "pycore_interp.h"        // _PyInterpreterState.sysdict
7 #include "pycore_long.h"          // _PyLong_GetOne()
8 #include "pycore_pathconfig.h"    // _PyPathConfig_ComputeSysPath0()
9 #include "pycore_pylifecycle.h"   // _Py_PreInitializeFromPyArgv()
10 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
11 #include "pycore_pythonrun.h"     // _PyRun_AnyFileObject()
12 
13 /* Includes for exit_sigint() */
14 #include <stdio.h>                // perror()
15 #ifdef HAVE_SIGNAL_H
16 #  include <signal.h>             // SIGINT
17 #endif
18 #if defined(HAVE_GETPID) && defined(HAVE_UNISTD_H)
19 #  include <unistd.h>             // getpid()
20 #endif
21 #ifdef MS_WINDOWS
22 #  include <windows.h>            // STATUS_CONTROL_C_EXIT
23 #endif
24 /* End of includes for exit_sigint() */
25 
26 #define COPYRIGHT \
27     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
28     "for more information."
29 
30 /* --- pymain_init() ---------------------------------------------- */
31 
32 static PyStatus
pymain_init(const _PyArgv * args)33 pymain_init(const _PyArgv *args)
34 {
35     PyStatus status;
36 
37     status = _PyRuntime_Initialize();
38     if (_PyStatus_EXCEPTION(status)) {
39         return status;
40     }
41 
42     PyPreConfig preconfig;
43     PyPreConfig_InitPythonConfig(&preconfig);
44 
45     status = _Py_PreInitializeFromPyArgv(&preconfig, args);
46     if (_PyStatus_EXCEPTION(status)) {
47         return status;
48     }
49 
50     PyConfig config;
51     PyConfig_InitPythonConfig(&config);
52 
53     /* pass NULL as the config: config is read from command line arguments,
54        environment variables, configuration files */
55     if (args->use_bytes_argv) {
56         status = PyConfig_SetBytesArgv(&config, args->argc, args->bytes_argv);
57     }
58     else {
59         status = PyConfig_SetArgv(&config, args->argc, args->wchar_argv);
60     }
61     if (_PyStatus_EXCEPTION(status)) {
62         goto done;
63     }
64 
65     status = Py_InitializeFromConfig(&config);
66     if (_PyStatus_EXCEPTION(status)) {
67         goto done;
68     }
69     status = _PyStatus_OK();
70 
71 done:
72     PyConfig_Clear(&config);
73     return status;
74 }
75 
76 
77 /* --- pymain_run_python() ---------------------------------------- */
78 
79 /* Non-zero if filename, command (-c) or module (-m) is set
80    on the command line */
config_run_code(const PyConfig * config)81 static inline int config_run_code(const PyConfig *config)
82 {
83     return (config->run_command != NULL
84             || config->run_filename != NULL
85             || config->run_module != NULL);
86 }
87 
88 
89 /* Return non-zero if stdin is a TTY or if -i command line option is used */
90 static int
stdin_is_interactive(const PyConfig * config)91 stdin_is_interactive(const PyConfig *config)
92 {
93     return (isatty(fileno(stdin)) || config->interactive);
94 }
95 
96 
97 /* Display the current Python exception and return an exitcode */
98 static int
pymain_err_print(int * exitcode_p)99 pymain_err_print(int *exitcode_p)
100 {
101     int exitcode;
102     if (_Py_HandleSystemExit(&exitcode)) {
103         *exitcode_p = exitcode;
104         return 1;
105     }
106 
107     PyErr_Print();
108     return 0;
109 }
110 
111 
112 static int
pymain_exit_err_print(void)113 pymain_exit_err_print(void)
114 {
115     int exitcode = 1;
116     pymain_err_print(&exitcode);
117     return exitcode;
118 }
119 
120 
121 /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
122    Return 0 otherwise. */
123 static int
pymain_get_importer(const wchar_t * filename,PyObject ** importer_p,int * exitcode)124 pymain_get_importer(const wchar_t *filename, PyObject **importer_p, int *exitcode)
125 {
126     PyObject *sys_path0 = NULL, *importer;
127 
128     sys_path0 = PyUnicode_FromWideChar(filename, wcslen(filename));
129     if (sys_path0 == NULL) {
130         goto error;
131     }
132 
133     importer = PyImport_GetImporter(sys_path0);
134     if (importer == NULL) {
135         goto error;
136     }
137 
138     if (importer == Py_None) {
139         Py_DECREF(sys_path0);
140         Py_DECREF(importer);
141         return 0;
142     }
143 
144     Py_DECREF(importer);
145     *importer_p = sys_path0;
146     return 0;
147 
148 error:
149     Py_XDECREF(sys_path0);
150 
151     PySys_WriteStderr("Failed checking if argv[0] is an import path entry\n");
152     return pymain_err_print(exitcode);
153 }
154 
155 
156 static int
pymain_sys_path_add_path0(PyInterpreterState * interp,PyObject * path0)157 pymain_sys_path_add_path0(PyInterpreterState *interp, PyObject *path0)
158 {
159     PyObject *sys_path;
160     PyObject *sysdict = interp->sysdict;
161     if (sysdict != NULL) {
162         sys_path = PyDict_GetItemWithError(sysdict, &_Py_ID(path));
163         if (sys_path == NULL && PyErr_Occurred()) {
164             return -1;
165         }
166     }
167     else {
168         sys_path = NULL;
169     }
170     if (sys_path == NULL) {
171         PyErr_SetString(PyExc_RuntimeError, "unable to get sys.path");
172         return -1;
173     }
174 
175     if (PyList_Insert(sys_path, 0, path0)) {
176         return -1;
177     }
178     return 0;
179 }
180 
181 
182 static void
pymain_header(const PyConfig * config)183 pymain_header(const PyConfig *config)
184 {
185     if (config->quiet) {
186         return;
187     }
188 
189     if (!config->verbose && (config_run_code(config) || !stdin_is_interactive(config))) {
190         return;
191     }
192 
193     fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform());
194     if (config->site_import) {
195         fprintf(stderr, "%s\n", COPYRIGHT);
196     }
197 }
198 
199 
200 static void
pymain_import_readline(const PyConfig * config)201 pymain_import_readline(const PyConfig *config)
202 {
203     if (config->isolated) {
204         return;
205     }
206     if (!config->inspect && config_run_code(config)) {
207         return;
208     }
209     if (!isatty(fileno(stdin))) {
210         return;
211     }
212 
213     PyObject *mod = PyImport_ImportModule("readline");
214     if (mod == NULL) {
215         PyErr_Clear();
216     }
217     else {
218         Py_DECREF(mod);
219     }
220     mod = PyImport_ImportModule("rlcompleter");
221     if (mod == NULL) {
222         PyErr_Clear();
223     }
224     else {
225         Py_DECREF(mod);
226     }
227 }
228 
229 
230 static int
pymain_run_command(wchar_t * command)231 pymain_run_command(wchar_t *command)
232 {
233     PyObject *unicode, *bytes;
234     int ret;
235 
236     unicode = PyUnicode_FromWideChar(command, -1);
237     if (unicode == NULL) {
238         goto error;
239     }
240 
241     if (PySys_Audit("cpython.run_command", "O", unicode) < 0) {
242         return pymain_exit_err_print();
243     }
244 
245     bytes = PyUnicode_AsUTF8String(unicode);
246     Py_DECREF(unicode);
247     if (bytes == NULL) {
248         goto error;
249     }
250 
251     PyCompilerFlags cf = _PyCompilerFlags_INIT;
252     cf.cf_flags |= PyCF_IGNORE_COOKIE;
253     ret = _PyRun_SimpleStringFlagsWithName(PyBytes_AsString(bytes), "<string>", &cf);
254     Py_DECREF(bytes);
255     return (ret != 0);
256 
257 error:
258     PySys_WriteStderr("Unable to decode the command from the command line:\n");
259     return pymain_exit_err_print();
260 }
261 
262 
263 static int
pymain_start_pyrepl_no_main(void)264 pymain_start_pyrepl_no_main(void)
265 {
266     int res = 0;
267     PyObject *console = NULL;
268     PyObject *empty_tuple = NULL;
269     PyObject *kwargs = NULL;
270     PyObject *console_result = NULL;
271 
272     PyObject *pyrepl = PyImport_ImportModule("_pyrepl.main");
273     if (pyrepl == NULL) {
274         fprintf(stderr, "Could not import _pyrepl.main\n");
275         res = pymain_exit_err_print();
276         goto done;
277     }
278     console = PyObject_GetAttrString(pyrepl, "interactive_console");
279     if (console == NULL) {
280         fprintf(stderr, "Could not access _pyrepl.main.interactive_console\n");
281         res = pymain_exit_err_print();
282         goto done;
283     }
284     empty_tuple = PyTuple_New(0);
285     if (empty_tuple == NULL) {
286         res = pymain_exit_err_print();
287         goto done;
288     }
289     kwargs = PyDict_New();
290     if (kwargs == NULL) {
291         res = pymain_exit_err_print();
292         goto done;
293     }
294     if (!PyDict_SetItemString(kwargs, "pythonstartup", _PyLong_GetOne())) {
295         _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
296         console_result = PyObject_Call(console, empty_tuple, kwargs);
297         if (!console_result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
298             _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
299         }
300         if (console_result == NULL) {
301             res = pymain_exit_err_print();
302         }
303     }
304 done:
305     Py_XDECREF(console_result);
306     Py_XDECREF(kwargs);
307     Py_XDECREF(empty_tuple);
308     Py_XDECREF(console);
309     Py_XDECREF(pyrepl);
310     return res;
311 }
312 
313 
314 static int
pymain_run_module(const wchar_t * modname,int set_argv0)315 pymain_run_module(const wchar_t *modname, int set_argv0)
316 {
317     PyObject *module, *runpy, *runmodule, *runargs, *result;
318     if (PySys_Audit("cpython.run_module", "u", modname) < 0) {
319         return pymain_exit_err_print();
320     }
321     runpy = PyImport_ImportModule("runpy");
322     if (runpy == NULL) {
323         fprintf(stderr, "Could not import runpy module\n");
324         return pymain_exit_err_print();
325     }
326     runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
327     if (runmodule == NULL) {
328         fprintf(stderr, "Could not access runpy._run_module_as_main\n");
329         Py_DECREF(runpy);
330         return pymain_exit_err_print();
331     }
332     module = PyUnicode_FromWideChar(modname, wcslen(modname));
333     if (module == NULL) {
334         fprintf(stderr, "Could not convert module name to unicode\n");
335         Py_DECREF(runpy);
336         Py_DECREF(runmodule);
337         return pymain_exit_err_print();
338     }
339     runargs = PyTuple_Pack(2, module, set_argv0 ? Py_True : Py_False);
340     if (runargs == NULL) {
341         fprintf(stderr,
342             "Could not create arguments for runpy._run_module_as_main\n");
343         Py_DECREF(runpy);
344         Py_DECREF(runmodule);
345         Py_DECREF(module);
346         return pymain_exit_err_print();
347     }
348     _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
349     result = PyObject_Call(runmodule, runargs, NULL);
350     if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
351         _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
352     }
353     Py_DECREF(runpy);
354     Py_DECREF(runmodule);
355     Py_DECREF(module);
356     Py_DECREF(runargs);
357     if (result == NULL) {
358         return pymain_exit_err_print();
359     }
360     Py_DECREF(result);
361     return 0;
362 }
363 
364 
365 static int
pymain_run_file_obj(PyObject * program_name,PyObject * filename,int skip_source_first_line)366 pymain_run_file_obj(PyObject *program_name, PyObject *filename,
367                     int skip_source_first_line)
368 {
369     if (PySys_Audit("cpython.run_file", "O", filename) < 0) {
370         return pymain_exit_err_print();
371     }
372 
373     FILE *fp = _Py_fopen_obj(filename, "rb");
374     if (fp == NULL) {
375         // Ignore the OSError
376         PyErr_Clear();
377         PySys_FormatStderr("%S: can't open file %R: [Errno %d] %s\n",
378                            program_name, filename, errno, strerror(errno));
379         return 2;
380     }
381 
382     if (skip_source_first_line) {
383         int ch;
384         /* Push back first newline so line numbers remain the same */
385         while ((ch = getc(fp)) != EOF) {
386             if (ch == '\n') {
387                 (void)ungetc(ch, fp);
388                 break;
389             }
390         }
391     }
392 
393     struct _Py_stat_struct sb;
394     if (_Py_fstat_noraise(fileno(fp), &sb) == 0 && S_ISDIR(sb.st_mode)) {
395         PySys_FormatStderr("%S: %R is a directory, cannot continue\n",
396                            program_name, filename);
397         fclose(fp);
398         return 1;
399     }
400 
401     // Call pending calls like signal handlers (SIGINT)
402     if (Py_MakePendingCalls() == -1) {
403         fclose(fp);
404         return pymain_exit_err_print();
405     }
406 
407     /* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
408     PyCompilerFlags cf = _PyCompilerFlags_INIT;
409     int run = _PyRun_AnyFileObject(fp, filename, 1, &cf);
410     return (run != 0);
411 }
412 
413 static int
pymain_run_file(const PyConfig * config)414 pymain_run_file(const PyConfig *config)
415 {
416     PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1);
417     if (filename == NULL) {
418         PyErr_Print();
419         return -1;
420     }
421     PyObject *program_name = PyUnicode_FromWideChar(config->program_name, -1);
422     if (program_name == NULL) {
423         Py_DECREF(filename);
424         PyErr_Print();
425         return -1;
426     }
427 
428     int res = pymain_run_file_obj(program_name, filename,
429                                   config->skip_source_first_line);
430     Py_DECREF(filename);
431     Py_DECREF(program_name);
432     return res;
433 }
434 
435 
436 static int
pymain_run_startup(PyConfig * config,int * exitcode)437 pymain_run_startup(PyConfig *config, int *exitcode)
438 {
439     int ret;
440     if (!config->use_environment) {
441         return 0;
442     }
443     PyObject *startup = NULL;
444 #ifdef MS_WINDOWS
445     const wchar_t *env = _wgetenv(L"PYTHONSTARTUP");
446     if (env == NULL || env[0] == L'\0') {
447         return 0;
448     }
449     startup = PyUnicode_FromWideChar(env, wcslen(env));
450     if (startup == NULL) {
451         goto error;
452     }
453 #else
454     const char *env = _Py_GetEnv(config->use_environment, "PYTHONSTARTUP");
455     if (env == NULL) {
456         return 0;
457     }
458     startup = PyUnicode_DecodeFSDefault(env);
459     if (startup == NULL) {
460         goto error;
461     }
462 #endif
463     if (PySys_Audit("cpython.run_startup", "O", startup) < 0) {
464         goto error;
465     }
466 
467     FILE *fp = _Py_fopen_obj(startup, "r");
468     if (fp == NULL) {
469         int save_errno = errno;
470         PyErr_Clear();
471         PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
472 
473         errno = save_errno;
474         PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, startup, NULL);
475         goto error;
476     }
477 
478     PyCompilerFlags cf = _PyCompilerFlags_INIT;
479     (void) _PyRun_SimpleFileObject(fp, startup, 0, &cf);
480     PyErr_Clear();
481     fclose(fp);
482     ret = 0;
483 
484 done:
485     Py_XDECREF(startup);
486     return ret;
487 
488 error:
489     ret = pymain_err_print(exitcode);
490     goto done;
491 }
492 
493 
494 /* Write an exitcode into *exitcode and return 1 if we have to exit Python.
495    Return 0 otherwise. */
496 static int
pymain_run_interactive_hook(int * exitcode)497 pymain_run_interactive_hook(int *exitcode)
498 {
499     PyObject *sys, *hook, *result;
500     sys = PyImport_ImportModule("sys");
501     if (sys == NULL) {
502         goto error;
503     }
504 
505     hook = PyObject_GetAttrString(sys, "__interactivehook__");
506     Py_DECREF(sys);
507     if (hook == NULL) {
508         PyErr_Clear();
509         return 0;
510     }
511 
512     if (PySys_Audit("cpython.run_interactivehook", "O", hook) < 0) {
513         goto error;
514     }
515 
516     result = _PyObject_CallNoArgs(hook);
517     Py_DECREF(hook);
518     if (result == NULL) {
519         goto error;
520     }
521     Py_DECREF(result);
522 
523     return 0;
524 
525 error:
526     PySys_WriteStderr("Failed calling sys.__interactivehook__\n");
527     return pymain_err_print(exitcode);
528 }
529 
530 
531 static void
pymain_set_inspect(PyConfig * config,int inspect)532 pymain_set_inspect(PyConfig *config, int inspect)
533 {
534     config->inspect = inspect;
535 _Py_COMP_DIAG_PUSH
536 _Py_COMP_DIAG_IGNORE_DEPR_DECLS
537     Py_InspectFlag = inspect;
538 _Py_COMP_DIAG_POP
539 }
540 
541 
542 static int
pymain_run_stdin(PyConfig * config)543 pymain_run_stdin(PyConfig *config)
544 {
545     if (stdin_is_interactive(config)) {
546         // do exit on SystemExit
547         pymain_set_inspect(config, 0);
548 
549         int exitcode;
550         if (pymain_run_startup(config, &exitcode)) {
551             return exitcode;
552         }
553 
554         if (pymain_run_interactive_hook(&exitcode)) {
555             return exitcode;
556         }
557     }
558 
559     /* call pending calls like signal handlers (SIGINT) */
560     if (Py_MakePendingCalls() == -1) {
561         return pymain_exit_err_print();
562     }
563 
564     if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
565         return pymain_exit_err_print();
566     }
567 
568     if (!isatty(fileno(stdin))
569         || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) {
570         PyCompilerFlags cf = _PyCompilerFlags_INIT;
571         int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
572         return (run != 0);
573     }
574     int run = pymain_run_module(L"_pyrepl", 0);
575     return (run != 0);
576 }
577 
578 
579 static void
pymain_repl(PyConfig * config,int * exitcode)580 pymain_repl(PyConfig *config, int *exitcode)
581 {
582     /* Check this environment variable at the end, to give programs the
583        opportunity to set it from Python. */
584     if (!config->inspect && _Py_GetEnv(config->use_environment, "PYTHONINSPECT")) {
585         pymain_set_inspect(config, 1);
586     }
587 
588     if (!(config->inspect && stdin_is_interactive(config) && config_run_code(config))) {
589         return;
590     }
591 
592     pymain_set_inspect(config, 0);
593     if (pymain_run_interactive_hook(exitcode)) {
594         return;
595     }
596 
597     if (PySys_Audit("cpython.run_stdin", NULL) < 0) {
598         return;
599     }
600 
601     if (!isatty(fileno(stdin))
602         || _Py_GetEnv(config->use_environment, "PYTHON_BASIC_REPL")) {
603         PyCompilerFlags cf = _PyCompilerFlags_INIT;
604         int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
605         *exitcode = (run != 0);
606         return;
607     }
608     int run = pymain_start_pyrepl_no_main();
609     *exitcode = (run != 0);
610     return;
611 }
612 
613 
614 static void
pymain_run_python(int * exitcode)615 pymain_run_python(int *exitcode)
616 {
617     PyObject *main_importer_path = NULL;
618     PyInterpreterState *interp = _PyInterpreterState_GET();
619     /* pymain_run_stdin() modify the config */
620     PyConfig *config = (PyConfig*)_PyInterpreterState_GetConfig(interp);
621 
622     /* ensure path config is written into global variables */
623     if (_PyStatus_EXCEPTION(_PyPathConfig_UpdateGlobal(config))) {
624         goto error;
625     }
626 
627     // XXX Calculate config->sys_path_0 in getpath.py.
628     // The tricky part is that we can't check the path importers yet
629     // at that point.
630     assert(config->sys_path_0 == NULL);
631 
632     if (config->run_filename != NULL) {
633         /* If filename is a package (ex: directory or ZIP file) which contains
634            __main__.py, main_importer_path is set to filename and will be
635            prepended to sys.path.
636 
637            Otherwise, main_importer_path is left unchanged. */
638         if (pymain_get_importer(config->run_filename, &main_importer_path,
639                                 exitcode)) {
640             return;
641         }
642     }
643 
644     // import readline and rlcompleter before script dir is added to sys.path
645     pymain_import_readline(config);
646 
647     PyObject *path0 = NULL;
648     if (main_importer_path != NULL) {
649         path0 = Py_NewRef(main_importer_path);
650     }
651     else if (!config->safe_path) {
652         int res = _PyPathConfig_ComputeSysPath0(&config->argv, &path0);
653         if (res < 0) {
654             goto error;
655         }
656         else if (res == 0) {
657             Py_CLEAR(path0);
658         }
659     }
660     // XXX Apply config->sys_path_0 in init_interp_main().  We have
661     // to be sure to get readline/rlcompleter imported at the correct time.
662     if (path0 != NULL) {
663         wchar_t *wstr = PyUnicode_AsWideCharString(path0, NULL);
664         if (wstr == NULL) {
665             Py_DECREF(path0);
666             goto error;
667         }
668         config->sys_path_0 = _PyMem_RawWcsdup(wstr);
669         PyMem_Free(wstr);
670         if (config->sys_path_0 == NULL) {
671             Py_DECREF(path0);
672             goto error;
673         }
674         int res = pymain_sys_path_add_path0(interp, path0);
675         Py_DECREF(path0);
676         if (res < 0) {
677             goto error;
678         }
679     }
680 
681     pymain_header(config);
682 
683     _PyInterpreterState_SetRunningMain(interp);
684     assert(!PyErr_Occurred());
685 
686     if (config->run_command) {
687         *exitcode = pymain_run_command(config->run_command);
688     }
689     else if (config->run_module) {
690         *exitcode = pymain_run_module(config->run_module, 1);
691     }
692     else if (main_importer_path != NULL) {
693         *exitcode = pymain_run_module(L"__main__", 0);
694     }
695     else if (config->run_filename != NULL) {
696         *exitcode = pymain_run_file(config);
697     }
698     else {
699         *exitcode = pymain_run_stdin(config);
700     }
701 
702     pymain_repl(config, exitcode);
703     goto done;
704 
705 error:
706     *exitcode = pymain_exit_err_print();
707 
708 done:
709     _PyInterpreterState_SetNotRunningMain(interp);
710     Py_XDECREF(main_importer_path);
711 }
712 
713 
714 /* --- pymain_main() ---------------------------------------------- */
715 
716 static void
pymain_free(void)717 pymain_free(void)
718 {
719     _PyImport_Fini2();
720 
721     /* Free global variables which cannot be freed in Py_Finalize():
722        configuration options set before Py_Initialize() which should
723        remain valid after Py_Finalize(), since
724        Py_Initialize()-Py_Finalize() can be called multiple times. */
725     _PyPathConfig_ClearGlobal();
726     _Py_ClearArgcArgv();
727     _PyRuntime_Finalize();
728 }
729 
730 
731 static int
exit_sigint(void)732 exit_sigint(void)
733 {
734     /* bpo-1054041: We need to exit via the
735      * SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled.
736      * If we don't, a calling process such as a shell may not know
737      * about the user's ^C.  https://www.cons.org/cracauer/sigint.html */
738 #if defined(HAVE_GETPID) && defined(HAVE_KILL) && !defined(MS_WINDOWS)
739     if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) {
740         perror("signal");  /* Impossible in normal environments. */
741     } else {
742         kill(getpid(), SIGINT);
743     }
744     /* If setting SIG_DFL failed, or kill failed to terminate us,
745      * there isn't much else we can do aside from an error code. */
746 #endif  /* HAVE_GETPID && !MS_WINDOWS */
747 #ifdef MS_WINDOWS
748     /* cmd.exe detects this, prints ^C, and offers to terminate. */
749     /* https://msdn.microsoft.com/en-us/library/cc704588.aspx */
750     return STATUS_CONTROL_C_EXIT;
751 #else
752     return SIGINT + 128;
753 #endif  /* !MS_WINDOWS */
754 }
755 
756 
757 static void _Py_NO_RETURN
pymain_exit_error(PyStatus status)758 pymain_exit_error(PyStatus status)
759 {
760     if (_PyStatus_IS_EXIT(status)) {
761         /* If it's an error rather than a regular exit, leave Python runtime
762            alive: Py_ExitStatusException() uses the current exception and use
763            sys.stdout in this case. */
764         pymain_free();
765     }
766     Py_ExitStatusException(status);
767 }
768 
769 
770 int
Py_RunMain(void)771 Py_RunMain(void)
772 {
773     int exitcode = 0;
774 
775     pymain_run_python(&exitcode);
776 
777     if (Py_FinalizeEx() < 0) {
778         /* Value unlikely to be confused with a non-error exit status or
779            other special meaning */
780         exitcode = 120;
781     }
782 
783     pymain_free();
784 
785     if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
786         exitcode = exit_sigint();
787     }
788 
789     return exitcode;
790 }
791 
792 
793 static int
pymain_main(_PyArgv * args)794 pymain_main(_PyArgv *args)
795 {
796     PyStatus status = pymain_init(args);
797     if (_PyStatus_IS_EXIT(status)) {
798         pymain_free();
799         return status.exitcode;
800     }
801     if (_PyStatus_EXCEPTION(status)) {
802         pymain_exit_error(status);
803     }
804 
805     return Py_RunMain();
806 }
807 
808 
809 int
Py_Main(int argc,wchar_t ** argv)810 Py_Main(int argc, wchar_t **argv)
811 {
812     _PyArgv args = {
813         .argc = argc,
814         .use_bytes_argv = 0,
815         .bytes_argv = NULL,
816         .wchar_argv = argv};
817     return pymain_main(&args);
818 }
819 
820 
821 int
Py_BytesMain(int argc,char ** argv)822 Py_BytesMain(int argc, char **argv)
823 {
824     _PyArgv args = {
825         .argc = argc,
826         .use_bytes_argv = 1,
827         .bytes_argv = argv,
828         .wchar_argv = NULL};
829     return pymain_main(&args);
830 }
831