Change the task priority temporary

I developed a firmware that has an embedded webserver. I use ESP32S3 MCU

For those who are curious about the product being mentioned: https://enervision.ind.br/produto/mqtt-view/

However, since my system is complex, and I have several tasks running at the same time.

To prevent the webserver from crashing, I had to increase the priority of the http task, as you can see below.

However, the webserver is a task that only serves for configuration purposes.

And it will only be done a few times by the user, it is not a task that is used all the time.

This task is not that important in the system.

I want to implement the following approach:

Have a global variable or something similar.

When loading the webserver for the first time… I change the priority of the task…

vTaskPrioritySet(TaskHandle_t xTask, UBaseType_t uxNewPriority);

After a specific period of inactivity I return to a lower priority.

I have not tested this possibility yet. (It seems to make sense to me).

But I would like to know the opinion of those of you who are more experienced.

What do you think?

If your web server CRASHES, that is a serious problem that you can not address with priority fiddling. Find the root cause for the crash and fix it.

What you possibly really mean is that the server gets starved and therefore becomes unresponsive.

Yes, that can happen, and there is not a whole lot you can do about it if your target is ressource limited. You need to weigh off functionality vs. configurability. Note also that security may also be affected as there may be denial of service attacks onto your device that may effictively starve your entire system if you run the server under high priority.

First:

Thank you for taking the time to help me.

I am very grateful for your attention.

There may be an error in the translation from my “Portuguese” to English (I use Google Translate).

When I say that my system “crashes” it is not exactly a “crash”.

It becomes slow, takes a long time to respond, and pages load poorly. I solved this problem by increasing the priority of the task, which made everything work perfectly.

However, the webserver remains at a high priority all the time.

Which is not exactly a desire on my part.

That’s why I’m eager to implement this change of priority.

If your web server is idle most of the time, it can not starve the rest of your system while no client is attached (unless you coded your server hapharzedly), so you will not benefit from raising the priority once a client is attached.

If your problem is that the server starves the rest of the system while there is a client session, you will not gain anything by bumping the priority with an active client session.

Dynamic priority adjustment of threads is perfectly legitimate in itself, but - just like everything else - has its place and needs to be applied where appropriate and useful.

In this case, you don’t see any sense in applying this priority change.

Considering that even though the webserver has high priority, it is not being used.

? Is that your opinion?

I thought that the fact that it has high priority leaves the rest of the system without resources.

No, the web server task is dormant until a client attaches, ie the web server is suspended on a call to attach() - at least if you follow the “standard” coding scheme. In that state, its priority is irrelevant as it is suspended.

1 Like

I didn’t know, is this a feature of ESP-IDF 5? Or something from free-rtos?

Neither nor, it is the way TCP servers are generally coded. If your web server was provided by prefabbed code in your IDE, you may want to look at the generated code to see how it behaves; maybe your tool vendor does things differently to make the web server task fit better into their framework. But generally a TCP server task should not consume any significant CPU time as long as there is not client attached.

But again, just because there is no one actively using the Web UI does not mean there is no client attached. DoS attacks is one frequent problem for carelessly written Web servers; another one may be network management systems that (legitemately or in bad intentions) probe each device in the given net for listening TCP ports. So your server may be invoked more frequently than you like to know.

1 Like

What security recommendations do you suggest to make the embedded web server more secure?

And to prevent it from being an easy target for DDoS attacks?

Change default http port 80?

first of all make sure that the user authentication is sufficiently strong to prevent malicious software to get into your web server, aside from the usual recommendations. However that is not going to help if an attacker bombards your target with SYN requests on your port. Other than that, there are plenty of sites out there full of recommendations for DoS protection.

But getting back to your original question: My point was that if you indeed raise your web server task’s priority without regard to legitimate/illegitimate connects, a DOS attacker could not only disrupt your service but also starve your target in total, so IF you follow a priority bumping strategy, make sure to raise the priority only after successfull authentication.

Thank you, I will implement security. At the moment the product has no security.

It doesn’t even have a login screen.

To build on top of what @RAc stated - which was very good. You don’t want to have a TCP task ‘busy looping’ in FreeRTOS. Thias will starve the FreeRTOS Idle task from execution which is not recommened. Instead, have your task be ‘dormant’ which can either be ‘suspended’ or ‘blocked’ from the viewpoint of the FreeRTOS-Kernel (I’d probably prefer suspended). When a client attaches you unsuspend/unblock the task and let it perform it’s work. At the end of it’s work the task would suspend/block itself.

As mentioned - security is important here and you’ll want robust authentication.

Really, you don’t want ANY task to busy loop. Perhaps a idle priority task could busy loop with a yield in the loop. Tasks should block until they have the ability to do work.

I would like to thank the community of this forum for their immense help and dedication.
Thank you very much

The colleague’s approach leaves me a little in doubt as to how to implement it in ESP-IDF 5 considering that I use a set of predefined instructions.

As you can see below.

I don’t know exactly how to implement the yield in the loop?

httpd_config_t config = HTTPD_DEFAULT_CONFIG();

void setupWebServer(int pages){
    pages+=48;
    config.max_uri_handlers = pages;
    config.max_resp_headers = 15;
    config.stack_size = 6000;//Estava em 10.000
    //config.task_priority = tskIDLE_PRIORITY+15;
    config.task_priority = configMAX_PRIORITIES - 1;
    //config.max_open_sockets = 7; //Ver o que dĂĄ 
    ESP_ERROR_CHECK(httpd_start(&server, &config));
    //Arquivos PĂĄginas Internas + .JS de cada PĂĄgina
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlIndex));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlConfigJson));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlConfigJS));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlMemory_list));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlOtaUpdate));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlOtaStatus));
    ESP_ERROR_CHECK(httpd_register_uri_handler(server, &urlOtaFactory));


}

What @richard-damon meant is that you should never have a task that never blocks. The only possible exception to that can be a task at IDLE priority which yields regularly:

void task( void * param )
{
    for( ;; )
    {
        /* Perform work. */

        taskYIELD();
    }
}

That seems like a question for Espressif.