Bugzilla – Bug 375
Ctrl-C does not always work when running Python simulations
Last modified: 2009-01-13 14:29:37 EST
Because Simulator::Run does not give back control to Python, unless there is some scheduled Python callback, so it never "notices" the signal.
Created attachment 342 [details] rough patch I had a first patch. The naive approach: while (!ns3::Simulator::IsFinished()) { if (PyEval_ThreadsInitialized()) py_thread_state = PyEval_SaveThread(); ns3::Simulator::RunOneEvent(); if (py_thread_state) PyEval_RestoreThread(py_thread_state); PyErr_CheckSignals(); if (PyErr_Occurred()) return NULL; } Problems: 1- I had to patch ns3::Simulator::IsFinished() to consider also the m_stop variable of the scheduler, otherwise my custom loop will ignore the Simulator::Stop() call; 2- Obviously there is an overhead of checking for signals on _every_ simulator iteration. On my system, the measured overhead (in the csma-bridge.py example) is 3.5% if the threading python module is not imported, or 4.3% with threading imported (there's an optimization that avoids the Python GIL calls if threading is not being used). I then modified the patch a bit. The attached patch takes a parameter 'signal_check_frequency', which is the number of iterations to run before checking for signals, or -1 to not check for signals at all. With the default value of 100, the overhead is only 0.7% for non-threaded programs, which I think is acceptable. Ctrl-C is, of course, very responsive. A better approach would be, perhaps, to create a thread which asks python to check for interrupts every second or so, and sets a global flag when interrupt is detected, so that the simulation loop can check for that variable, which should have less overhead. But I think this patch is much less complicated and has reasonably low overhead, so I'll settle for it, if no objections. I have to ask, what to do with the Simulator::IsFinished change? Is it OK to commit, or propose a new API call to do what I want, or...?
Committed a cleaned up patch.