LCOV - code coverage report
Current view: top level - Modules - main.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 252 343 73.5 %
Date: 2022-07-07 18:19:46 Functions: 25 26 96.2 %

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

Generated by: LCOV version 1.14