Skip to content

Commit a527058

Browse files
author
Anselm Kruis
committed
Stackless issue python#88: Fix assertion violation caused by
stackless.current.switch() Fix an assertion violation caused by incorrect usage of ts->st.del_post_switch. Add a test case for "switch to current". This commit also adds the test class TestTaskletSwitching, which was only in 2.7-slp. https://bitbucket.org/stackless-dev/stackless/issues/88 (grafted from f0db3bdf1061, b85b07e9f10effdbf52adc71d452d1e93bd3c5fd, 782a1b292460 and 7d9b4398011f)
1 parent 5a06d86 commit a527058

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

Stackless/module/taskletobject.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ impl_tasklet_run_remove(PyTaskletObject *task, int remove)
747747
STACKLESS_GETARG();
748748
PyThreadState *ts = PyThreadState_GET();
749749
PyObject *ret;
750-
int inserted, fail, removed=0;
750+
int inserted, fail, switched, removed=0;
751751
PyTaskletObject *prev = ts->st.current;
752752

753753
assert(PyTasklet_Check(task));
@@ -814,9 +814,10 @@ impl_tasklet_run_remove(PyTaskletObject *task, int remove)
814814
if (fail)
815815
return NULL;
816816
/* this is redundant in the interthread case, since insert already did the work */
817-
fail = slp_schedule_task(&ret, prev, task, stackless, 0);
817+
fail = slp_schedule_task(&ret, prev, task, stackless, &switched);
818818
if (fail) {
819819
if (removed) {
820+
assert(ts->st.del_post_switch == (PyObject *)prev);
820821
ts->st.del_post_switch = NULL;
821822
slp_current_unremove(prev);
822823
}
@@ -825,6 +826,8 @@ impl_tasklet_run_remove(PyTaskletObject *task, int remove)
825826
slp_current_uninsert(task);
826827
Py_DECREF(task);
827828
}
829+
} else if (!switched) {
830+
Py_CLEAR(ts->st.del_post_switch);
828831
}
829832
return ret;
830833
}

Stackless/unittests/test_miscell.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,35 @@ def test_aliveness3(self):
133133
self.assertEqual(t.recursion_depth, 0)
134134

135135

136+
class TestTaskletSwitching(StacklessTestCase):
137+
"""Test the tasklet's own scheduling methods"""
138+
139+
def test_raise_exception(self):
140+
c = stackless.channel()
141+
142+
def foo():
143+
self.assertRaises(IndexError, c.receive)
144+
s = stackless.tasklet(foo)()
145+
s.run() # necessary, since raise_exception won't automatically run it
146+
s.raise_exception(IndexError)
147+
148+
def test_run(self):
149+
c = stackless.channel()
150+
flag = [False]
151+
152+
def foo():
153+
flag[0] = True
154+
s = stackless.tasklet(foo)()
155+
s.run()
156+
self.assertEqual(flag[0], True)
157+
158+
def test_switch_to_current(self):
159+
# See https://bitbucket.org/stackless-dev/stackless/issues/88
160+
current = stackless.current
161+
current.switch()
162+
current.switch() # this second switch used to trigger an assertion violation
163+
164+
136165
class TestTaskletThrowBase(object):
137166

138167
def test_throw_noargs(self):

0 commit comments

Comments
 (0)