Skip to content

Commit a973618

Browse files
committed
Core - Fix port reload
1 parent d44e1d6 commit a973618

1 file changed

Lines changed: 94 additions & 14 deletions

File tree

src/webui.c

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,9 @@ static bool _webui_mutex_is_thread_running(_webui_window_t* win, int update);
680680
static bool _webui_mutex_is_start_requested(_webui_window_t* win, int update);
681681
static bool _webui_mutex_is_reload_requested(_webui_window_t* win, int update);
682682
static void _webui_window_request_reload(_webui_window_t* win);
683+
static void _webui_window_wait_for_reload(_webui_window_t* win);
684+
static bool _webui_window_thread_end(_webui_window_t* win);
685+
static bool _webui_window_cycle_end(_webui_window_t* win);
683686
static _webui_window_t* _webui_dereference_win_num(size_t num);
684687
static void _webui_start_server_thread(_webui_window_t* win);
685688
static void _webui_window_close_ui(_webui_window_t* win);
@@ -3617,6 +3620,9 @@ const char* webui_get_url(size_t window) {
36173620
if (win == NULL)
36183621
return NULL;
36193622

3623+
// Report the URL of the new server if a reload is pending
3624+
_webui_window_wait_for_reload(win);
3625+
36203626
// Check if local server is started
36213627
if (_webui_is_empty(win->url)) {
36223628
// Start local server
@@ -6545,8 +6551,10 @@ static bool _webui_mutex_is_reload_requested(_webui_window_t* win, int update) {
65456551
static void _webui_window_request_reload(_webui_window_t* win) {
65466552

65476553
// Ask the persistent server thread of a window to restart its web
6548-
// server using the current settings. If clients are connected they
6549-
// get closed first: the thread reloads once the serve cycle ends.
6554+
// server using the current settings. The flag also ends the current
6555+
// serve cycle, so the thread reaches the reload immediately. The
6556+
// connected clients are asked to close: they are bound to the old
6557+
// server, which is about to be stopped.
65506558

65516559
#ifdef WEBUI_LOG
65526560
_webui_log_debug("[Core]\t\t_webui_window_request_reload([%zu])\n", win->num);
@@ -6557,6 +6565,50 @@ static void _webui_window_request_reload(_webui_window_t* win) {
65576565
webui_close(win->num);
65586566
}
65596567

6568+
static void _webui_window_wait_for_reload(_webui_window_t* win) {
6569+
6570+
// Wait for a pending reload of this window to complete. The reload
6571+
// flag stays set until the web server is listening again, so after
6572+
// this the window port and URL are the final ones.
6573+
6574+
if (!_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS))
6575+
return;
6576+
6577+
#ifdef WEBUI_LOG
6578+
_webui_log_debug("[Core]\t\t_webui_window_wait_for_reload([%zu])\n", win->num);
6579+
#endif
6580+
6581+
_webui_timer_t timer;
6582+
_webui_timer_start(&timer);
6583+
for (;;) {
6584+
_webui_sleep(1);
6585+
if (!_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS))
6586+
break;
6587+
if (!_webui_mutex_is_thread_running(win, WEBUI_MUTEX_GET_STATUS))
6588+
break;
6589+
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS))
6590+
break;
6591+
if (_webui_timer_is_end(&timer, 5000))
6592+
break;
6593+
}
6594+
}
6595+
6596+
static bool _webui_window_thread_end(_webui_window_t* win) {
6597+
6598+
// Should the persistent server thread of this window exit?
6599+
return (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) ||
6600+
_webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS));
6601+
}
6602+
6603+
static bool _webui_window_cycle_end(_webui_window_t* win) {
6604+
6605+
// Should the current serve cycle of this window end? A reload ends
6606+
// the cycle as well, so the server gets restarted right away instead
6607+
// of waiting for the connection timeouts to expire.
6608+
return (_webui_window_thread_end(win) ||
6609+
_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS));
6610+
}
6611+
65606612
static void _webui_window_task_count(_webui_window_t* win, int delta) {
65616613

65626614
_webui_mutex_lock(&win->mutex_win_thread);
@@ -9496,6 +9548,11 @@ static bool _webui_show_window_impl(_webui_window_t* win, struct mg_connection*
94969548
}
94979549
#endif
94989550

9551+
// A pending reload is about to change this window's port and URL.
9552+
// Let the server thread finish it first, so this show uses the
9553+
// new ones instead of pointing the UI at the old server.
9554+
_webui_window_wait_for_reload(win);
9555+
94999556
// Initialization
95009557
bool keep_user_index_file = false;
95019558
if (type == WEBUI_SHOW_URL && win->url != NULL && !_webui_is_empty(content)) {
@@ -11084,6 +11141,7 @@ static WEBUI_THREAD_SERVER_START {
1108411141
// and stays listening until this thread exits.
1108511142
struct mg_context * http_ctx = NULL;
1108611143
char* server_port = NULL;
11144+
bool resume_after_reload = false;
1108711145

1108811146
// This thread is persistent: it parks until `webui_show()` requests a
1108911147
// serve cycle, serves until the window gets closed, then parks again.
@@ -11092,25 +11150,26 @@ static WEBUI_THREAD_SERVER_START {
1109211150

1109311151
// Park: wait for a serve request, a client
1109411152
// re-connection, or a reload request
11095-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS))
11153+
if (_webui_window_thread_end(win))
1109611154
break;
1109711155

1109811156
// Reload: restart the web server of this window using the
1109911157
// current settings. Requested by setters like `webui_set_port()`.
11100-
// The requester closes this window's clients, so the reload runs
11101-
// once the serve cycle has ended and the clients are gone.
11158+
// The reload request also ended the serve cycle, so we get here
11159+
// immediately. The reload flag stays set until the server is
11160+
// listening again, so `webui_show()` waits for the new port.
1110211161
bool rebind_only = false;
11103-
if (_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS) &&
11104-
!_webui_mutex_is_connected(win, WEBUI_MUTEX_GET_STATUS)) {
11105-
11106-
_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_SET_FALSE);
11162+
if (_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS)) {
1110711163

1110811164
if (http_ctx != NULL) {
1110911165

1111011166
#ifdef WEBUI_LOG
1111111167
_webui_log_debug("[Core]\t\t_webui_server_thread([%zu]) -> Reloading server...\n", win->num);
1111211168
#endif
1111311169

11170+
// Any remaining client is bound to the old server
11171+
_webui_mutex_is_connected(win, WEBUI_MUTEX_SET_FALSE);
11172+
1111411173
// Wait for this window's in-flight event tasks, then
1111511174
// stop the server services
1111611175
_webui_window_wait_for_tasks(win);
@@ -11136,6 +11195,10 @@ static WEBUI_THREAD_SERVER_START {
1113611195
// Restart listening right away, then park again
1113711196
rebind_only = true;
1113811197
}
11198+
else {
11199+
// Nothing to reload, the server was never started
11200+
_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_SET_FALSE);
11201+
}
1113911202
}
1114011203

1114111204
if (!rebind_only) {
@@ -11225,6 +11288,9 @@ static WEBUI_THREAD_SERVER_START {
1122511288
win->server_port = 0;
1122611289
_webui_free_mem((void*)server_port);
1122711290
server_port = NULL;
11291+
11292+
// A failed reload is still a finished reload
11293+
_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_SET_FALSE);
1122811294
continue;
1122911295
}
1123011296

@@ -11246,8 +11312,17 @@ static WEBUI_THREAD_SERVER_START {
1124611312
}
1124711313

1124811314
if (rebind_only) {
11315+
1124911316
// The reload is done. The server is listening
1125011317
// again, using the new settings
11318+
_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_SET_FALSE);
11319+
11320+
// Resume serving if this window was serving when the reload
11321+
// was requested, so it stays active for `webui_wait()`
11322+
if (resume_after_reload) {
11323+
resume_after_reload = false;
11324+
_webui_mutex_is_start_requested(win, WEBUI_MUTEX_SET_TRUE);
11325+
}
1125111326
continue;
1125211327
}
1125311328

@@ -11291,7 +11366,7 @@ static WEBUI_THREAD_SERVER_START {
1129111366
_webui_sleep(1);
1129211367

1129311368
// Stop if we get exit signal
11294-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS)) {
11369+
if (_webui_window_cycle_end(win)) {
1129511370
stop = true;
1129611371
break;
1129711372
}
@@ -11328,7 +11403,7 @@ static WEBUI_THREAD_SERVER_START {
1132811403
for (;;) {
1132911404

1133011405
// Stop if we get exit signal
11331-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS)) {
11406+
if (_webui_window_cycle_end(win)) {
1133211407
stop = true;
1133311408
break;
1133411409
}
@@ -11380,7 +11455,7 @@ static WEBUI_THREAD_SERVER_START {
1138011455
_webui_sleep(1);
1138111456

1138211457
// Exit signal
11383-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS)) {
11458+
if (_webui_window_cycle_end(win)) {
1138411459
stop = true;
1138511460
break;
1138611461
}
@@ -11416,7 +11491,7 @@ static WEBUI_THREAD_SERVER_START {
1141611491
for (;;) {
1141711492

1141811493
// Stop if we get exit signal
11419-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS)) {
11494+
if (_webui_window_cycle_end(win)) {
1142011495
stop = true;
1142111496
break;
1142211497
}
@@ -11481,7 +11556,7 @@ static WEBUI_THREAD_SERVER_START {
1148111556
// Wait forever
1148211557
for (;;) {
1148311558
_webui_sleep(1);
11484-
if (_webui_mutex_app_is_exit_now(WEBUI_MUTEX_GET_STATUS) || _webui_mutex_win_is_exit_now(win, WEBUI_MUTEX_GET_STATUS))
11559+
if (_webui_window_cycle_end(win))
1148511560
break;
1148611561
}
1148711562
}
@@ -11495,6 +11570,11 @@ static WEBUI_THREAD_SERVER_START {
1149511570
_webui_mutex_is_connected(win, WEBUI_MUTEX_SET_FALSE);
1149611571
_webui_window_close_ui(win);
1149711572

11573+
// A reload ended this cycle. Serving resumes once
11574+
// the server is listening again.
11575+
if (_webui_mutex_is_reload_requested(win, WEBUI_MUTEX_GET_STATUS))
11576+
resume_after_reload = true;
11577+
1149811578
// Make window reusable, so user can
1149911579
// call `webui_show()` again if needed.
1150011580
_webui_make_window_reusable(win);

0 commit comments

Comments
 (0)