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

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions