embassy icon indicating copy to clipboard operation
embassy copied to clipboard

UdpSocket created and used inside async function doesn't work properly

Open yanshay opened this issue 2 years ago • 6 comments

I wrote a small program (ESP32/no_std, using embassy/embassy-net) that sends UDP packets and it work just fine.

When I moved the networking related code into an async function, it stopped working, UDP Packets wouldn't be sent. Everything seemed to progress properly w/o any errors, but the packets weren't sent.

I pinpointed it to the move of the UdpSocket::new into the async function. Once it moved into the async function the packets weren't sent. For the program to work, the UdpSocket has to be created in the main() and all the rest can run inside the async function.

I thought it might have to do with #2175 but the buffers are created in the main function which never ends (so exist before and after the networking code, so no memory issues). I tried letting the executor run after calling the new (using Time::after) , in case something needs to be processed before continuing in the net_task of .

Any ideas what's the reason? Is this maybe by design?

yanshay avatar Nov 16 '23 18:11 yanshay

could it be that you're creating the socket, sending some packet, then immediately dropping the socket?

"sending" the packets only enqueues them in the socket buffers, the socket needs to "stick around" for them to actually be sent.

Dirbaio avatar Nov 16 '23 19:11 Dirbaio

could it be that you're creating the socket, sending some packet, then immediately dropping the socket?

"sending" the packets only enqueues them in the socket buffers, the socket needs to "stick around" for them to actually be sent.

The buffers are in the main function, so never dropped. I await the send_to and then return from the function, so the socket is dropped then. Does the send_to.await return before the UDP packet is actually sent? If so, then why does it need to be awaited? And how can I wait until it gets sent?

yanshay avatar Nov 16 '23 22:11 yanshay

The buffers are in the main function, so never dropped. I await the send_to and then return from the function, so the socket is dropped then.

The buffers don't matter, it's the socket what must not get dropped.

Does the send_to.await return before the UDP packet is actually get sent? If

"send_to" only enqueues them in the socket buffers, the socket needs to "stick around" for them to actually be sent.

If so, then why does it need to be awaited?

if the socket buffers are full, it waits until some packets are sent so there's free space.

And how can I wait until it gets sent?

Currently, the only way is to not drop the socket. We could add a async fn flush(&mut self) to wait for all queued packets to be sent, like TCP has. PRs are welcome if you'd be interested in adding it.

Dirbaio avatar Nov 16 '23 22:11 Dirbaio

Encountered the same problem today.

I am interested in implementing a flush function for this, @Dirbaio any directions?

ProfFan avatar Oct 18 '24 19:10 ProfFan

Ok this is blocked by https://github.com/smoltcp-rs/smoltcp/issues/838

ProfFan avatar Oct 19 '24 18:10 ProfFan

Pushed PR on upstream for exporting the necessary symbols

ProfFan avatar Oct 19 '24 19:10 ProfFan

This issue can be closed?

ProfFan avatar Oct 23 '24 01:10 ProfFan

@Dirbaio

ProfFan avatar Oct 23 '24 01:10 ProfFan