Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Lib/test/test_asyncio/test_futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,16 @@ def test_future_disallow_multiple_initialization(self):
with self.assertRaises(RuntimeError, msg="is already initialized"):
f.__init__(loop=self.loop)

def test_futureiter_send_after_throw_no_crash(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have an additional test case for the it.close() similar to this.

fut = self._new_future(loop=self.loop)
it = fut.__await__()
next(it)
with self.assertRaises(RuntimeError):
it.throw(RuntimeError)
with self.assertRaises(StopIteration):
it.send(None)


@unittest.skipUnless(hasattr(futures, '_CFuture'),
'requires the C _asyncio module')
class CFutureTests(BaseFutureTests, test_utils.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix a crash in asyncio.Future iterator when send() is
called after throw() or close().
5 changes: 5 additions & 0 deletions Modules/_asynciomodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,11 @@ FutureIter_am_send(PyObject *op,
PyObject **result)
{
futureiterobject *it = (futureiterobject*)op;
if (it->future == NULL) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but reading it->future outside the critical section looks unsafe.

This was the previous reviewer's @kumaraditya303 review comment.

There is also a read happening in FutureIter_am_send_lock_held (line 1832) which is called from FutureIter_am_send

After reading it->future in a critical section, sending the same object might address it.

@VanshAgarwal24036, I noticed the PR has become state. Would you like to revive it again with these change ?

PyErr_SetNone(PyExc_StopIteration);
*result = NULL;
return PYGEN_ERROR;
}
/* arg is unused, see the comment on FutureIter_send for clarification */
PySendResult res;
Py_BEGIN_CRITICAL_SECTION(it->future);
Expand Down
Loading