-
Notifications
You must be signed in to change notification settings - Fork 112
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
Address several ESP32 network driver issues #1137
Conversation
#ifdef CONFIG_AVM_ENABLE_NETWORK_PORT_DRIVER | ||
|
||
REGISTER_PORT_DRIVER(network, network_driver_init, NULL, network_driver_create_port) | ||
REGISTER_PORT_DRIVER(network, network_driver_init, network_driver_stop, network_driver_create_port) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
network_driver_stop
will not be called when calling network:stop/0
. It gets called during tests (when GlobalContext is destoryed and recreated).
So this change sounds correct, but it doesn't do what you are saying.
908bd03
to
40b8959
Compare
Thank you for the explanation of the These problems have all been fixed, and the driver shuts down and exits cleanly. There is still one ESP-IDF message (in some builds, depending on the IDF version) in the console logs that is being reported as an error:
I looked into this and it is actually a known ESP-IDF issue, that will be changed to an information message in a future update. See espressif/esp-idf#12473. |
40b8959
to
8eb624e
Compare
a222bd4
to
dfa2f88
Compare
6063cca
to
2623f6d
Compare
@@ -723,7 +744,6 @@ static void start_network(Context *ctx, term pid, term ref, term config) | |||
if ((err = esp_wifi_set_config(ESP_IF_WIFI_AP, ap_wifi_config)) != ESP_OK) { | |||
ESP_LOGE(TAG, "Error setting AP mode config %d", err); | |||
free(ap_wifi_config); | |||
free(sta_wifi_config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how this causes a crash. Can you elaborate further?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pointer has already been free'd between lines 703 and 715. Freeing it again will cause a double-free crash, this is an error condition already - but we want the user to get a nice Erlang stack trace (or catch the error), rather than a hard crash of the VM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to look at the sources, but I'm not understanding what you mean here. Can you elaborate further?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bettio I understand the crash could also be avoided if sta_wifi_config was set to NULL after line 716 (old) 736 (new). If sta_wifi_config was not NULL, it is freed anyway in the block above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is from release-0.6:
https://github.com/atomvm/AtomVM/blob/eb406a82e15c53d77304d30ceabcfc67a2d5e593/src/platforms/esp32/components/avm_builtins/network_driver.c#L724C1-L738C6
if (!IS_NULL_PTR(sta_wifi_config)) {
if ((err = esp_wifi_set_config(ESP_IF_WIFI_STA, sta_wifi_config)) != ESP_OK) {
ESP_LOGE(TAG, "Error setting STA mode config %d", err);
free(sta_wifi_config);
if (!IS_NULL_PTR(ap_wifi_config)) {
free(ap_wifi_config);
}
term error = port_create_error_tuple(ctx, term_from_int(err));
port_send_reply(ctx, pid, ref, error);
return;
} else {
ESP_LOGI(TAG, "STA mode configured");
free(sta_wifi_config);
}
}
Either path through this code will free(sta_wifi_config)
. Freeing again below will cause a hard fault.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bettio I understand the crash could also be avoided if sta_wifi_config was set to NULL after line 716 (old) 736 (new). If sta_wifi_config was not NULL, it is freed anyway in the block above.
This might be an easier way to avoid the bug, but I still am not a fan of freeing the same variable multiple times, it always makes me have to stop an re-examine the code the next time I’m working on a feature, because it looks suspicious.
That is awesome, however I need a complete understanding about how this fix is working during the review... |
d2bbaaf
to
0d68f33
Compare
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
This driver offers resource based nif APIs using unit and channel resources, as well as a set of convenient gen_server based APIs, which use pin numbers, as an alternative to using the nif resource handles. Unit 2 is currently disabled for the ESP32C3 by default due to known hardware limitations, see: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/api-reference/peripherals/adc_oneshot.html#hardware-limitations Unit 2 is currently disabled by default for the ESP32 (classic) due to WiFi conflicts. This decision can be revisited after PR atomvm#1137 is merged, and the WiFi driver can be successfully stopped after it has been started. Unit 2 is enabled by default for all other chips with more than one ADC unit, as the chips released after the ESP32 classic have a functional ADC arbitrator peripheral that allows ADC unit 2 use while WiFi is enabled. Signed-off-by: Winford <winford@object.stream>
Removes several possible uses of free() on memory that had been previously free'd. This would happen under specific error conditions in the `start_network` function in network_driver.c that `network:start/1` uses to configure and start the network. Signed-off-by: Winford <winford@object.stream>
…SP32 Adds a destroy callback to the ESP32 network driver to completely stop the driver and free all network resources when network:stop/0 is used. Previosly the driver was not being stopped internally and resources were not freed when the gen_server was stopped, causing instability, and possible crashes when event callbacks were triggered, but there was no process alive to handle them. Closes atomvm#643 Signed-off-by: Winford <winford@object.stream>
Adds an event handler for `event 21` the `WIFI_EVENT_STA_BEACON_TIMEOUT` event and an option to add an Erlang callback handler for the event. The event will be logged with an info level message that includes a suggestion about the two most likely causes, poor rssi and network congestion. A callback config option `{beacon_timeout, fun()}` may be added to the `sta` config. Closes atomvm#1100 Signed-off-by: Winford <winford@object.stream>
0d68f33
to
ec7602c
Compare
These changes close the following issues for the ESP32 network driver:
network:stop/0
#643] When network:stop/0 is used the driver is now completely stopped and all resources are freed.These changes are made under both the "Apache 2.0" and the "GNU Lesser General
Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later