Skip to content

Commit

Permalink
For now, turn assert on green_switch results into an explicit excepti…
Browse files Browse the repository at this point in the history
…on. Add some debugging for the crash seen on Linux/Win.
  • Loading branch information
jamadden committed Sep 7, 2023
1 parent 9a4c053 commit 42d856a
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
14 changes: 10 additions & 4 deletions src/greenlet/greenlet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ single_result(const OwnedObject& results)
&& PyTuple_Check(results.borrow())
&& PyTuple_GET_SIZE(results.borrow()) == 1) {
PyObject* result = PyTuple_GET_ITEM(results.borrow(), 0);
assert(result);
return OwnedObject::owning(result);
}
return results;
Expand Down Expand Up @@ -1060,7 +1061,7 @@ UserGreenlet::g_switch()
try {
this->check_switch_allowed();
}
catch(const PyErrOccurred&) {
catch (const PyErrOccurred&) {
this->release_args();
throw;
}
Expand Down Expand Up @@ -1641,7 +1642,6 @@ Greenlet::g_switch_finish(const switchstack_result_t& err)
// Our only caller handles the bad error case
assert(err.status >= 0);
assert(state.borrow_current() == this->self());

if (OwnedObject tracefunc = state.get_tracefunc()) {
g_calltrace(tracefunc,
result ? mod_globs->event_switch : mod_globs->event_throw,
Expand All @@ -1660,7 +1660,6 @@ Greenlet::g_switch_finish(const switchstack_result_t& err)
// be reached after a test run.
throw PyErrOccurred();
}

return result;
}
catch (const PyErrOccurred&) {
Expand Down Expand Up @@ -2310,7 +2309,14 @@ green_switch(PyGreenlet* self, PyObject* args, PyObject* kwargs)
assert(!current->args());
#endif
PyObject* p = result.relinquish_ownership();
assert(p || PyErr_Occurred());
if (!p && !PyErr_Occurred()) {
// Temporary: Crash "gracefully" in this case. Figure out
// how it is happening and make sure it doesn't.
throw PyErrOccurred(
mod_globs->PyExc_GreenletError,
"Greenlet.switch() returned NULL without an exception set."
);
}
return p;
}
catch(const PyErrOccurred&) {
Expand Down
1 change: 1 addition & 0 deletions src/greenlet/greenlet_exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ namespace greenlet {
{
PyErr_SetString(exc_kind, msg);
}

PyErrOccurred(PyObject* exc_kind, const std::string msg)
: std::runtime_error(msg)
{
Expand Down
20 changes: 15 additions & 5 deletions src/greenlet/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,22 +177,32 @@ def get_expected_returncodes_for_aborted_process(self):
)
return expected_exit

def run_script(self, script_name):
def run_script(self, script_name, show_output=True):
import subprocess
import os
script = os.path.join(
os.path.dirname(__file__),
script_name,
)

return subprocess.check_output([sys.executable, script],
encoding='utf-8',
stderr=subprocess.STDOUT)
try:
subprocess.check_output([sys.executable, script],
encoding='utf-8',
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as ex:
if show_output:
print('-----')
print('Failed to run script', script)
print('~~~~~')
print(ex.output)
print('------')
raise


def assertScriptRaises(self, script_name, exitcodes=None):
import subprocess
with self.assertRaises(subprocess.CalledProcessError) as exc:
output = self.run_script(script_name)
output = self.run_script(script_name, show_output=False)
__traceback_info__ = output
# We're going to fail the assertion if we get here, at least
# preserve the output in the traceback.
Expand Down

0 comments on commit 42d856a

Please sign in to comment.