Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential MethodQueue bug? #63

Open
2 tasks done
jheinnic opened this issue Aug 21, 2020 · 1 comment
Open
2 tasks done

Potential MethodQueue bug? #63

jheinnic opened this issue Aug 21, 2020 · 1 comment

Comments

@jheinnic
Copy link

Checklist

  • I have included information about relevant versions
  • I have verified that the issue persists when using the master branch of Mode.

Steps to reproduce

  1. Define any simple async function
  2. Create a mode.threads.QueueServiceThread and call its start() method.
  3. Call the async function with service.
  4. Prepare a debugger with breakpoints at two locations:
    -- The beginning of MethodQueue, currently line 331 of mode/threads.py
    -- The if self._loop is None block of ServiceBase's loop @property, currently line 146 of mode/services.py
  5. Run with the debugger
  6. Observe first expected Breakpoint stop
  7. Resume execution

Expected behavior

The program should run to completion without stopping at the second breakpoint at all

Before proceeding to (7), notice that we have passed an explicit event loop argument. I do not expect to need to hit the second breakpoint before the program completes because the event loop is known at this point and I have no further Service initialization to do.

Actual behavior

Given that we have passed a loop argument explicitly to MethodQueue, I would not expect to land in the second breakpoint, especially while the first breakpoint is still on the call stack. But on resuming after the first, expected breakpoint, we land in a second, unexpected stop, with MethodQueue requesting the default event loop to satisfy its own None reference.

Reading the code carefully we can see that MethodQueue does not ever do anything with its EventLoop parameter--neither pass it to its own super.init() method, more to any of its child objects.

I imagine that this code should either not receive an EventLoop argument, or it should pass that argument to its own call to ServiceBase.init() before initializing its Queue and Event objects. I am not sure which solution would be preferred. Although the former seems more consistent with Python 3.8's deprecation of explicit EventLoop arguments, perhaps the latter would be more sensitive to compatibility with Python 3.6 and 3.7 for the time being.

Full traceback

Traceback (most recent call last):
  __init__, threads.py:332
  method_queue, threads.py:411
  on_thread_started, threads.py:418
  _serve, threads.py:252
  _run, events.py:81
  _run_once, base_events.py:1859
  run_forever, base_events.py:570
  run_until_complete, base_events.py:603
  _start_thread, threads.py:211
  run, threads.py:66
    _bootstrap_inner, threading.py:932
    _bootstrap, threading.py:890

Versions

  • Python version 3.8.5
  • Mode version 4.3.2
  • Operating system MacOSX 10.13.6
@jheinnic
Copy link
Author

Code block that implements (1) to (3)

import asyncio
from mode import QueueServiceThread


async def my_func(a: int) -> None:
    print(a)


async def use_queue_service() -> None:
    service: QueueServiceThread = QueueServiceThread()
    await service.start();
    await service.call_thread(my_func, 5)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(
        use_queue_service()
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant