-
Notifications
You must be signed in to change notification settings - Fork 7.6k
v1.0.3: Network stack never recovers without a hard reset after receiving a fixed number of UDP packets #3287
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
Comments
I did some more testing with different packet sizes, and for me, it always fails at 32 packets. |
After even more testing, even for very slow packet rates, eg. 0.5Hz ( |
Yep. When I change this value to something else, the failure always happens at that number of packets. For example, when CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM is 43, it fails at 43 packets, etc. |
@ssilverman try calling the packet destructor when you are finished with the packet: void onPacket(AsyncUDPPacket &packet) {
Serial.printf("%d: %d\n", ++counter, packet.length());
delete packet; // all done free resources
} Chuck. |
@stickbreaker That doesn't work and causes crashes. (I changed to |
This is not at about 32 packets, but at 32 packets exactly. Not even closely spaced. Are sockets not getting closed? |
It look like asynchUdp is not freeing the buffer after you use it. I added a call to This is the code where your handler is called: void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port, struct netif * netif)
{
while(pb != NULL) {
pbuf * this_pb = pb;
pb = pb->next;
this_pb->next = NULL;
if(_handler) {
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
_handler(packet);
++ pbuf_free(this_pb); // try adding this line
} else {
pbuf_free(this_pb);
}
}
} |
I solved the problem by changing the (Note that this agrees with the notes inside and linked from #2899.) |
@lbernstone You're right. I'm adjusting the issue title... |
@ssilverman so, what does your working code look like? |
@stickbreaker I changed the void onPacket(AsyncUDPPacket packet) {
Serial.printf("%d: %d\n", ++counter, packet.length());
} But, according to your code paste, Update: Turns out the |
@ssilverman Yes, that was my question. |
Thinking about why (per my update two comments above) the |
@ssilverman that buffer needs to be freed somewhere. If I am reading the code correctly it only frees the buffer element if there is no callback? Without a callback how does the data get returned to the user? my recommendation for I think the Or, are you saying by changing the function you can receive continuous packet streams? Chuck. |
the |
Pass pointers, not references. That makes a copy of the object and holds it open. |
@ssilverman I think I figured it out. if(_handler) {
AsyncUDPPacket packet(this, this_pb, addr, port, netif);
_handler(packet);
} yes @lbernstone It finally donned on me! you are correct, the copy object was the guilty party! Chuck. |
The literal definition of a fnord. It took me 3 looks to see it. |
I think I get what's happening:
So:
In other words, no matter which version we're using there's a leak. Does my assessment look correct? If not, which part is incorrect? |
@lbernstone Thank you, you just gave me a new word fnord I had never heard of it before. |
@stickbreaker looks like we commented at the same time :) Update: I'm wrong for the second case. There's no current leak for the copy-constructor version. |
Here's my proposed fix:
This should cover both the pass-as-reference and pass-as-copy cases. |
@ssilverman I'm studying your fix. |
@stickbreaker the troubling fact is that the code still works even when compiling with a copy constructor for When writing the copy constructor, it sucks that we can't just create a default and call |
@stickbreaker (re. #3287 (comment)). The To pass something that takes a reference, just pass the object, not its address. Don't prepend the Update: The comments to which I'm referring were deleted. |
@stickbreaker message me offline, I'd be happy to chat about this. I don't want to dilute this issue too much. :) Update: The comments to which I'm referring were deleted. |
…ack for both pass-as-reference and pass-as-copy versions. See espressif#3287 and espressif#3288.
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
There's still no explanation about why the proposed fix in #3290 doesn't work. The pass-by-reference version in AsyncUDP is still broken. |
[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future. |
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. |
My fix was taken, but uncredited: #3290 (comment) |
This is the same bug as #2899, but for v1.0.3.
Hardware:
Board: Adafruit ESP32 Feather
Core Installation version: Core v1.0.3 in Arduino 1.8.10
IDE name: Arduino v1.8.10
Flash Frequency: 80MHz
PSRAM enabled: Don't know
Upload Speed: 921600
Computer OS: Mac OSX v10.14.6
Description:
I refer the reader to the main description in #2899, but in summary, here are two programs for testing.
To continuously send closely-spaced packets (in bash):
[Change the IP address to your board's IP address.]
You'll notice that after about 32 packets, no more packets are received.
Sketch:
The text was updated successfully, but these errors were encountered: