Estou tentando armazenar uma solicitação HTTP como uma variável global. Meu software é sobre conexão WiFi, e a biblioteca WiFi que estou usando é baseada em eventos, o que significa que devo armazenar a solicitação HTTP em algum lugar e esperar por um retorno de chamada em eventos. Problema: o programa trava depois que tento acessá-lo novamente. Log:
> Guru Meditation Error: Core 0 panic'ed (StoreProhibited). Exception
> was unhandled.
>
> Core 0 register dump: PC : 0x400ff5e5 PS : 0x00060430 A0
> : 0x800d79a1 A1 : 0x3ffbdf90
> --- 0x400ff5e5: httpd_resp_send at F:/Espressif/frameworks/esp-idf-v5.2.5/components/esp_http_server/src/httpd_txrx.c:248
>
> A2 : 0x3ffc93c8 A3 : 0x3f4038ec A4 : 0x00000003 A5
> : 0x00000000 A6 : 0x00000000 A7 : 0x3ffc93c8 A8 :
> 0x00000000 A9 : 0x3ffbdf30 A10 : 0x000001f4 A11 :
> 0x3ffbdf30 A12 : 0x3ffbde44 A13 : 0x3ffbde0c A14 :
> 0x3ffbde20 A15 : 0x3ffbdff0 SAR : 0x00000004 EXCCAUSE:
> 0x0000001d EXCVADDR: 0x00000218 LBEG : 0x400014fd LEND :
> 0x4000150d LCOUNT : 0xffffffff
> --- 0x400014fd: strlen in ROM
> --- 0x4000150d: strlen in ROM
>
>
>
> Backtrace: 0x400ff5e2:0x3ffbdf90 0x400d799e:0x3ffbdfd0
> 0x400d773b:0x3ffbdff0 0x400d7ad1:0x3ffbe020 0x4016387d:0x3ffbe050
> 0x401633c6:0x3ffbe080 0x401634a1:0x3ffbe0c0 0x4008a129:0x3ffbe0e0
> --- 0x400ff5e2: httpd_resp_send at F:/Espressif/frameworks/esp-idf-v5.2.5/components/esp_http_server/src/httpd_txrx.c:248
> --- 0x400d799e: wifi_setup_handle_response at F:/Documents/dashboardfordevice/device-software/main/wifi_setup_webpage.c:44
> --- 0x400d773b: disconnect_handler at F:/Documents/dashboardfordevice/device-software/main/wifi_manager.c:20
> --- 0x400d7ad1: run_on_event at F:/Documents/dashboardfordevice/device-software/main/wifi.c:32
> --- 0x4016387d: handler_execute at F:/Espressif/frameworks/esp-idf-v5.2.5/components/esp_event/esp_event.c:137
> --- 0x401633c6: esp_event_loop_run at F:/Espressif/frameworks/esp-idf-v5.2.5/components/esp_event/esp_event.c:593
> --- 0x401634a1: esp_event_loop_run_task at F:/Espressif/frameworks/esp-idf-v5.2.5/components/esp_event/esp_event.c:107
> --- 0x4008a129: vPortTaskWrapper at F:/Espressif/frameworks/esp-idf-v5.2.5/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:13
pelo que entendi, isso é causado por uma string nula a princípio, mas esta é a linha 44 emwifi_setup_webpage.c, httpd_resp_send(request, "200", 3);
o que, pelo que sei, não pode ser o problema, considerando que meus outros manipuladores que fazem a mesma coisa não travam, a única diferença é que o ponteiro deles para a solicitação é "fresh".
Eu armazeno a solicitação usando uma variável global: httpd_req_t* request;
e então a atribuo usando request = req;
o código completo para esse método:
esp_err_t connect_post_handler(httpd_req_t *req)
{
size_t size = req->content_len;
if (size > 1024) {
// too big
const char* response = "Content too massive, but you know what else is massive?";
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, response);
return ESP_OK;
}
char content[1024];
int bytes_read = httpd_req_recv(req, content, size);
if (bytes_read == 0) {
// connection closed
return ESP_ERR_HTTPD_INVALID_REQ;
}
cJSON* jsonData = cJSON_ParseWithLength(content, size);
if (jsonData == NULL) {
// json parsing failed, bad request
const char* response = "Bad JSON format";
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, response);
return ESP_OK;
}
char* ssid = cJSON_GetObjectItem(jsonData, "ssid")->valuestring;
char* password = cJSON_GetObjectItem(jsonData, "password")->valuestring;
cJSON_Delete(jsonData);
request = req;
reconnect_callback(ssid, password);
return ESP_OK;
}
e o código completo do método que envia a solicitação:
void wifi_setup_handle_response(bool boolean, const char * response)
{
// cJSON* response_data = cJSON_CreateObject();
// cJSON_AddBoolToObject(response_data, "success", boolean);
// cJSON_AddStringToObject(response_data, "message", response);
// char* response_string = cJSON_Print(response_data);
// ESP_LOGI(LOG_TAG, "Raw Response: %s", response_string);
// if (response_string == NULL) {
// // failed
// ESP_LOGE(LOG_TAG, "Could not write wifi connect response to string");
// httpd_resp_send_500(request);
// cJSON_Delete(response_data);
// return;
// }
if (request == NULL) {
ESP_LOGE(LOG_TAG, "request is null, aha!");
return;
}
httpd_resp_send(request, "200", 3);
// free(response_string);
// cJSON_Delete(response_data);
}
Para sua informação: há um intervalo de ~3 segundos entre essas duas funções. order: connect_post_handler THEN void wifi_setup_handle_response. Acho que é porque algo relacionado à memória da pilha está sendo destruída, então o ponteiro para ela não é mais válido, mas não sei como lidar com isso, já que o typedef da solicitação tem muitos ponteiros sofisticados para outras coisas.
Uma instância de solicitação HTTP só é válida até que o retorno de chamada do manipulador de solicitação seja retornado.
Se você quiser usar uma instância de solicitação fora do retorno de chamada do manipulador, você deve usar httpd_req_async_handler_begin() para fazer uma cópia da solicitação que você pode usar posteriormente em outro lugar. Chame httpd_req_async_handler_complete() para excluir a cópia quando não for mais necessária.
Veja também https://github.com/espressif/esp-idf/tree/v5.4.1/examples/protocols/http_server/async_handlers