This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Py_AddPendingCall Inserted Function Never Called in 3.8, works in 3.6
Type: behavior Stage:
Components: C API Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: chrisgmorton
Priority: normal Keywords:

Created on 2021-03-12 22:11 by chrisgmorton, last changed 2022-04-11 14:59 by admin.

Messages (2)
msg388559 - (view) Author: Chris Morton (chrisgmorton) Date: 2021-03-12 22:11
Building code on Mac OSX or Linux Ubuntu 16.04

#include <Python.h>
#include <thread>
#include <chrono>
#include <iostream>

// MacOSX build:
// g++ stop.cpp -I <prod root dir>/include/pythonX.X -L <prod root dir>/lib -lpythonX.X -o stop
// Linuxe requires addtional linkage:
// -lpthread

void RunPythonScript()
{
    PyRun_SimpleString("# import sys \n"
                       "import time \n"
                       "# sys.setcheckinterval(-1) \n"
                       "while True: \n"
                       "    print('Running!') \n"
                       "    time.sleep(1) \n"
                       );

    std::cout << "Terminating Python Interpreter." << std::endl;
}

int Stop(void *)
{
    std::cout << "We threw an exception." <<std::endl;    
    PyErr_SetInterrupt();
    PyErr_SetString(PyExc_RuntimeError, "Stop Python Execution.");
    return -1;

}

int main (int argc, char *argv[])
{

    Py_Initialize(); // The Python Interpreter must be created in the main thread.
    
    std::thread th(&RunPythonScript);    // Now execute our python scipt in a thread.

    std::cout << "Python has started!" << std::endl;    
    std::this_thread::sleep_for(std::chrono::seconds(5));
    
    std::cout << "Asking Python to exit." << std::endl;

    PyGILState_STATE state = PyGILState_Ensure();    
    int r = Py_AddPendingCall(&Stop, NULL); // inject our Stop routine
    std::cout << r <<std::endl;
    PyGILState_Release(state);
    
    th.join(); // Wait for the thread to catch up. 

    Py_Finalize();

    std::cout << "Exiting Main Function." << std::endl;
    
    std::this_thread::sleep_for(std::chrono::seconds(2));
    
return 0;
}

Linking against 3.6 and executing leads to the successful interruption of Python code execution:

Python has started!
Running!
Running!
Running!
Running!
Running!
Asking Python to exit.
0
We threw an exception.
Traceback (most recent call last):
  File "<string>", line 6, in <module>
RuntimeError: Stop Python Execution.
Terminating Python Interpreter.
Exiting Main Function.

The Stop function is never called with the same code linked against Python 3.8.
msg388704 - (view) Author: Chris Morton (chrisgmorton) Date: 2021-03-15 03:28
I should add that Py_AddPendingCall returns 0 in both cases.
History
Date User Action Args
2022-04-11 14:59:42adminsetgithub: 87648
2021-03-15 03:29:17chrisgmortonsettitle: Py_AddPendingCall Function Never Called in 3.8, works in 3.6 -> Py_AddPendingCall Inserted Function Never Called in 3.8, works in 3.6
2021-03-15 03:28:04chrisgmortonsettype: behavior
messages: + msg388704
title: PyAddPendingCall Function Never Called in 3.8, works in 3.6 -> Py_AddPendingCall Function Never Called in 3.8, works in 3.6
2021-03-12 22:11:40chrisgmortoncreate