| 166 | } |
| 167 | |
| 168 | void loop() { |
| 169 | vTaskPrioritySet(NULL, 2); |
| 170 | static size_t tries = 0; |
| 171 | try { |
| 172 | // Start the main loop. Processes program inputs and executes them. |
| 173 | // This can exit on a system abort condition, in which case run_once() |
| 174 | // is re-executed by an enclosing loop. It can also exit via a |
| 175 | // throw that is caught and handled below. |
| 176 | protocol_main_loop(); |
| 177 | } catch (std::exception& ex) { |
| 178 | // If an assertion fails, we display a message and restart. |
| 179 | // This could result in repeated restarts if the assertion |
| 180 | // happens before waiting for input, but that is unlikely |
| 181 | // because the code in reset_variables() and the code |
| 182 | // that precedes the input loop has few configuration |
| 183 | // dependencies. The safest approach would be to set |
| 184 | // a "reconfiguration" flag and redo the configuration |
| 185 | // step, but that would require combining main_init() |
| 186 | // and run_once into a single control flow, and it would |
| 187 | // require careful teardown of the existing configuration |
| 188 | // to avoid memory leaks. It is probably worth doing eventually. |
| 189 | log_config_error("Critical error in run_once: " << ex.what()); |
| 190 | } |
| 191 | // sys.abort is a user-initiated exit via ^x so we don't limit the number of occurrences |
| 192 | if (!sys.abort() && ++tries > 1) { |
| 193 | log_info("Stalling due to too many failures"); |
| 194 | while (1) {} |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | void WEAK_LINK machine_init() {} |
| 199 |
no test coverage detected