robertsdotpm / p2pd

Asynchronous P2P networking library and service
MIT License
48 stars 2 forks source link

Task was destroyed but it is pending! #16

Closed super-creative-0 closed 1 month ago

super-creative-0 commented 7 months ago

Hi! This is my first bug, so please correct me if I'm wrong, or remind me if the information I provided is unclear.

I'm following your docs for instructions for how to use p2pd. But, as soon as I use the example code, p2pd crashes. I used multiple examples, but the code still fails.

Name: p2pd Version: 2.8.0 Summary: Asynchronous P2P networking library and service Home-page: http://github.com/robertsdotpm/p2pd Author: Matthew Roberts Author-email: matthew@roberts.pm License: public domain Location: C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages Requires: aiosqlite, aiounittest, argon2pure, ecdsa, gmqtt, ntplib, xmltodict Required-by:

For example, I tried this: ` from p2pd import *

async def example(): i = await Interface().start()

await i.load_nat()
repr(i)

if name == 'main': async_test(example) `

And, it fails with this:

python exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-118' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-119' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-120' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-122' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-125' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-126' coro=<nat_test_workers.<locals>.worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>}

I don't know what is happening. The REST API works without any errors, but when I copied the code for the REST API server and tried to run it, the same errors occured, with no traceback. Is it because the API server is frozen, so it works and isn't affected by the bug?

It also seems to have database errors when using start_p2p_node() :

python Traceback (most recent call last): File "d:\Data\Documents\ProjectComet\client.py", line 91, in <module> async_test(example) File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\utils.py", line 616, in async_test loop.run_until_complete(f()) File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete return future.result() ^^^^^^^^^^^^^^^ File "d:\Data\Documents\ProjectComet\client.py", line 74, in example node_a = await computer_a() ^^^^^^^^^^^^^^^^^^ File "d:\Data\Documents\ProjectComet\client.py", line 33, in computer_a await node.register(COMPUTER_A_NAME) File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\p2p_node.py", line 292, in register out, status = await self.irc_dns.name_register(*name_field[:3]) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\irc_dns.py", line 1448, in name_register if success_no < await self.get_register_success_min(): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\irc_dns.py", line 1314, in get_register_success_min return await self.get_server_len() - await self.get_register_failure_max() ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\irc_dns.py", line 1298, in get_server_len last_started = await self.db.get(last_started_key, start) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\sqlite_kvs.py", line 67, in get cursor = await self.db.execute(query, (key,)) ^^^^^^^ AttributeError: 'SqliteKVS' object has no attribute 'db' exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-431' coro=<async_wrap_errors() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\utils.py:385> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-427' coro=<MQTTProtocol._read_loop() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\mqtt\protocol.py:211> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-428' coro=<Client.reconnect() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\client.py:265> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[MqttPackageHandler._handle_exception_in_future()]>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-421' coro=<MQTTProtocol._read_loop() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\mqtt\protocol.py:211> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-486' coro=<Client._resend_qos_messages() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\client.py:181> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-485' coro=<Client._resend_qos_messages() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\client.py:181> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-430' coro=<async_wrap_errors() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\utils.py:385> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-461' coro=<Client._resend_qos_messages() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\gmqtt\client.py:177> wait_for=<Future pending cb=[Task.task_wakeup()]>>} exception handler {'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-432' coro=<Event.wait() running at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\asyncio\locks.py:213> wait_for=<Future pending cb=[Task.task_wakeup()]> cb=[_release_waiter(<Future pendi...ask_wakeup()]>)() at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\asyncio\tasks.py:421]>}

Thank you, and if you have any suggestions for me to improve my bug reporting or need more info, please tell me. (Sorry for the messed up formatting.)

robertsdotpm commented 7 months ago

Have you done anything with asyncio in Python before because I'd start there? Everything in p2pd is designed to be called from async functions and not standard function. You can try out the examples by using the p2pd shell: python3 -m p2pd. It seems that the function to launch async functions in p2pd has broken. Will look into it.

By the way -- the example that uses IRC DNS probably won't work either. The idea for IRC DNS is not a very good one and I haven't bothered maintaining it. P2PD still doesn't have a good design for naming node addresses. But I think I have some good ideas now to solve that.

C:\Users\matth\projects\p2pd\docs\source\python\examples>python3 -m p2pd P2PD 2.7.9 REPL on Python 3.11 / win32 Loop = selector, Process = spawn Use "await" directly instead of "asyncio.run()".

from p2pd import * i = await Interface() i

It's 4 am here right now (insomnia, lol) but I thought I would give you a quick reply now. P2PD has had a lot of work done to it but I still need to make it much more user-friendly. This is proving to be a challenging problem though.

super-creative-0 commented 7 months ago

Okay, thank you for your quick reply!

robertsdotpm commented 5 months ago

I'm curious about the first example you posted with the nat loading. When you print the interface print(i) does it have addresses loaded in there (like can you see your IP?) Or has it completely failed to load relevant network addresses?

Beet-Meat-Burger commented 5 months ago

No, it completely failed with an exception.

robertsdotpm commented 5 months ago

What OS are you running? If you set P2PD_DEBUG=1 as an environmental variable and run the example is there anything that stands out to you in program.log? If you run python3 -m unittest in tests directory what tests are broken for you?

Beet-Meat-Burger commented 5 months ago

Don't have time to test it out yet. I will try it out later.

robertsdotpm commented 5 months ago

Don't have time to test it out yet. I will try it out later.

sure, no problem

Beet-Meat-Burger commented 4 months ago

I haven't ran the tests fully(no patience, sorry!), but they don't have the problem discribed before. It seems to work fine. I ran the tests straight out of the unzipped file from Github.

This still occurs with the first example:

from p2pd import *

async def example(): i = await Interface().start() await i.load_nat() repr(i)

if name == 'main': async_test(example)

{'message': 'Task was destroyed but it is pending!', 'task': <Task pending name='Task-126' coro=<nat_test_workers..worker() done, defined at C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\p2pd\nat_test.py:154> wait_for=<Future pending cb=[Task.task_wakeup()]>>}

Changing the code to this:

from p2pd import *

async def example(): i = await Interface().start() await i.load_nat() print(repr(i))

asyncio.run(example())

I get info about my interface.

Interface.from_dict({'id': 6, 'is_default': {2: True, 23: False}, 'mac': '8C-55-4A-D3-C4-80', 'name': 'Intel(R) Wi-Fi 6 AX201 160MHz', 'nat': {'delta': {'type': 2, 'value': 0}, 'delta_info': 'equal delta (local port == mapped port)', 'nat_info': 'restrict port', 'type': 5}, 'nic_no': 6, 'rp': {2: [{'af': 2, 'ext_ips': [{'af': 2, 'cidr': 32, 'ip': '182.153.56.153'}], 'nic_ips': [{'af': 2, 'cidr': 32, 'ip': '192.168.8.42'}]}], 23: []}})

async_test() broken?

It has been quite a long while since I made this issue. Sorry for the blurry details before.

robertsdotpm commented 4 months ago

It's working then. async_test just calls loop.run_until_complete. The issue is that it doesn't allow time for proper cleanup. It will run the coroutine and then end immediately. Adding a sleep fixes it but kind of a bad solution. I'll keep the issue open until I think of something because this seems like a more complex issue with async in Python.

Beet-Meat-Burger commented 4 months ago

Interesting to know. Thanks!

robertsdotpm commented 1 month ago

made some changes to use async.run over my crappy helper function where its available. this helps with task cleanup