Skip to content

Investigate asyncio compiler error #6736

@youknowone

Description

@youknowone

Summary

Originally reported from: #6601 (comment)

Details

written by @terryluan12


As an update, I've narrowed down the hang to an issue in the wait method of the Condition class. I think it's an issue with the AST generation? (but not 100%)

The test that is failing is test_locks.ConditionTests.test_cancelled_error_re_aquire
The relevant function is below

async def wait(self):
    """Wait until notified.

    If the calling task has not acquired the lock when this
    method is called, a RuntimeError is raised.

    This method releases the underlying lock, and then blocks
    until it is awakened by a notify() or notify_all() call for
    the same condition variable in another task.  Once
    awakened, it re-acquires the lock and returns True.

    This method may return spuriously,
    which is why the caller should always
    re-check the state and be prepared to wait() again.
    """
    if not self.locked():
        raise RuntimeError('cannot wait on un-acquired lock')

    fut = self._get_loop().create_future()
    self.release()
    try:
        try:
            self._waiters.append(fut)
            try:
                await fut                          # A) It reaches here fine
                return True
            finally:
                self._waiters.remove(fut)

        finally:
            # Must re-acquire lock even if wait is cancelled.
            # We only catch CancelledError here, since we don't want any
            # other (fatal) errors with the future to cause us to spin.
            err = None
            while True:                             # B) The code enters a loop here to reacquire the lock
                try:
                    await self.acquire()            # C) While waiting here, the task is cancelled
                    break
                except exceptions.CancelledError as e:
                    err = e                         # D) The code reaches here fine

            if err is not None:
                try:
                    raise err                       # E) The error is reraised here
                finally:
                    err = None                      # F) It reaches here
    except BaseException:
        self._notify(1)                             # G) It is supposed to exit here
        raise

Whereas in CPython, the program is supposed to go from F) to G), RustPython instead goes from F) to B), re-entering the final statement again (reaquiring the lock again at C), reaching a deadlock state, and hanging.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions