Skip to content

Commit 9d8e6a8

Browse files
committed
Fix data race in win-connected
* Adding mutex for win->connected
1 parent 8084a02 commit 9d8e6a8

File tree

1 file changed

+59
-29
lines changed

1 file changed

+59
-29
lines changed

src/webui.c

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
#define WEBUI_PROTOCOL_ID (5) // Protocol byte position: ID (2 Bytes)
4949
#define WEBUI_PROTOCOL_CMD (7) // Protocol byte position: Command (1 Byte)
5050
#define WEBUI_PROTOCOL_DATA (8) // Protocol byte position: Data (n Byte)
51+
#define WEBUI_MUTEX_NONE (0) // Check boolen mutex without update
52+
#define WEBUI_MUTEX_TRUE (1) // Check boolen mutex and update to true
53+
#define WEBUI_MUTEX_FALSE (2) // Check boolen mutex and update to false
5154
#define WEBUI_WS_DATA (1) // Internal WS Event (Data received)
5255
#define WEBUI_WS_OPEN (2) // Internal WS Event (New connection)
5356
#define WEBUI_WS_CLOSE (3) // Internal WS Event (Connection close)
@@ -201,6 +204,7 @@ typedef struct _webui_core_t {
201204
webui_mutex_t mutex_wait;
202205
webui_mutex_t mutex_bridge;
203206
webui_mutex_t mutex_js_run;
207+
webui_mutex_t mutex_win_connect;
204208
webui_condition_t condition_wait;
205209
char* default_server_root_path;
206210
bool ui;
@@ -339,6 +343,8 @@ static const char* _webui_url_encode(const char* str);
339343
static bool _webui_open_url_native(const char* url);
340344
static bool _webui_is_valid_url(const char* url);
341345
static bool _webui_port_is_used(size_t port_num);
346+
static bool _webui_mtx_is_connected(_webui_window_t * win, int update);
347+
static bool _webui_mtx_is_exit_now(int update);
342348
#ifdef WEBUI_TLS
343349
static int _webui_tls_initialization(void * ssl_ctx, void * ptr);
344350
static bool _webui_tls_generate_self_signed_cert(char* root_cert, char* root_key, char* ssl_cert, char* ssl_key);
@@ -410,7 +416,7 @@ void webui_run(size_t window, const char* script) {
410416
return;
411417
_webui_window_t * win = _webui_core.wins[window];
412418

413-
if (!win->connected)
419+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
414420
return;
415421

416422
// Packet Protocol Format:
@@ -459,7 +465,7 @@ bool webui_script(size_t window, const char* script, size_t timeout_second, char
459465
if (buffer_length > 0)
460466
memset(buffer, 0, buffer_length);
461467

462-
if (!win->connected)
468+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
463469
return false;
464470

465471
size_t js_len = _webui_strlen(script);
@@ -662,7 +668,7 @@ void webui_close(size_t window) {
662668
return;
663669
_webui_window_t * win = _webui_core.wins[window];
664670

665-
if (win->connected) {
671+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
666672

667673
// Packet Protocol Format:
668674
// [...]
@@ -710,7 +716,7 @@ void webui_destroy(size_t window) {
710716
#endif
711717

712718
// Forced close
713-
win->connected = false;
719+
_webui_mtx_is_connected(win, WEBUI_MUTEX_FALSE);
714720

715721
// Wait for server threads to stop
716722
_webui_timer_t timer_2;
@@ -760,7 +766,7 @@ bool webui_is_shown(size_t window) {
760766
return false;
761767
_webui_window_t * win = _webui_core.wins[window];
762768

763-
return win->connected;
769+
return _webui_mtx_is_connected(win, WEBUI_MUTEX_NONE);
764770
}
765771

766772
void webui_set_icon(size_t window, const char* icon, const char* icon_type) {
@@ -814,7 +820,7 @@ void webui_navigate(size_t window, const char* url) {
814820
return;
815821
_webui_window_t * win = _webui_core.wins[window];
816822

817-
if (!win->connected)
823+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
818824
return;
819825

820826
// Packet Protocol Format:
@@ -1127,12 +1133,12 @@ size_t webui_bind(size_t window, const char* element, void( * func)(webui_event_
11271133
// to this UI. We need to send this new binding
11281134
// ID to to the UI.
11291135

1130-
if (!win->connected) {
1136+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
11311137
_webui_timer_t timer;
11321138
_webui_timer_start( & timer);
11331139
for (;;) {
11341140
_webui_sleep(10);
1135-
if (win->connected)
1141+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
11361142
break;
11371143
if (_webui_timer_is_end( & timer, 3000))
11381144
break;
@@ -1719,7 +1725,7 @@ void webui_set_size(size_t window, unsigned int width, unsigned int height) {
17191725
win->height = height;
17201726
win->size_set = true;
17211727

1722-
if (win->connected) {
1728+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
17231729

17241730
// Resize the current window
17251731
char script[128];
@@ -1752,7 +1758,7 @@ void webui_set_position(size_t window, unsigned int x, unsigned int y) {
17521758
win->y = y;
17531759
win->position_set = true;
17541760

1755-
if (win->connected) {
1761+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
17561762

17571763
// Positioning the current window
17581764
char script[128];
@@ -3400,7 +3406,7 @@ static const char* _webui_generate_js_bridge(_webui_window_t * win) {
34003406
uint32_t token = 0;
34013407

34023408
// Get Token Authorization
3403-
if (!win->connected) {
3409+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
34043410
// First connection
34053411
token = win->token;
34063412
}
@@ -3478,6 +3484,28 @@ static const char* _webui_generate_js_bridge(_webui_window_t * win) {
34783484
return js;
34793485
}
34803486

3487+
static bool _webui_mtx_is_connected(_webui_window_t * win, int update) {
3488+
3489+
bool status = false;
3490+
_webui_mutex_lock( & _webui_core.mutex_win_connect);
3491+
if (update == WEBUI_MUTEX_TRUE) win->connected = true;
3492+
else if (update == WEBUI_MUTEX_FALSE) win->connected = false;
3493+
status = win->connected;
3494+
_webui_mutex_unlock( & _webui_core.mutex_win_connect);
3495+
return status;
3496+
}
3497+
3498+
static bool _webui_mtx_is_exit_now(int update) {
3499+
3500+
bool status = false;
3501+
_webui_mutex_lock( & _webui_core.mutex_win_connect);
3502+
if (update == WEBUI_MUTEX_TRUE) _webui_core.exit_now = true;
3503+
else if (update == WEBUI_MUTEX_FALSE) _webui_core.exit_now = false;
3504+
status = _webui_core.exit_now;
3505+
_webui_mutex_unlock( & _webui_core.mutex_win_connect);
3506+
return status;
3507+
}
3508+
34813509
static bool _webui_browser_create_new_profile(_webui_window_t * win, size_t browser) {
34823510

34833511
#ifdef WEBUI_LOG
@@ -4652,6 +4680,7 @@ static void _webui_clean(void) {
46524680
_webui_mutex_destroy( & _webui_core.mutex_receive);
46534681
_webui_mutex_destroy( & _webui_core.mutex_wait);
46544682
_webui_mutex_destroy( & _webui_core.mutex_js_run);
4683+
_webui_mutex_destroy( & _webui_core.mutex_win_connect);
46554684
_webui_condition_destroy( & _webui_core.condition_wait);
46564685

46574686
#ifdef WEBUI_LOG
@@ -5788,7 +5817,7 @@ static bool _webui_show_window(_webui_window_t * win, const char* content, int t
57885817
}
57895818

57905819
// Run the web-browser window
5791-
if (!win->connected) {
5820+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
57925821

57935822
// Start a new window
57945823

@@ -5921,7 +5950,7 @@ static void _webui_ws_send(_webui_window_t * win, char* packet, size_t packets_s
59215950
printf("]\n");
59225951
#endif
59235952

5924-
if (!win->connected || packet == NULL || packets_size < WEBUI_PROTOCOL_SIZE)
5953+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE) || packet == NULL || packets_size < WEBUI_PROTOCOL_SIZE)
59255954
return;
59265955

59275956
int ret = 0;
@@ -6058,6 +6087,7 @@ static void _webui_init(void) {
60586087
_webui_mutex_init( & _webui_core.mutex_wait);
60596088
_webui_mutex_init( & _webui_core.mutex_bridge);
60606089
_webui_mutex_init( & _webui_core.mutex_js_run);
6090+
_webui_mutex_init( & _webui_core.mutex_win_connect);
60616091
_webui_condition_init( & _webui_core.condition_wait);
60626092

60636093
// // Determine whether the current device
@@ -6461,7 +6491,7 @@ static int _webui_ws_connect_handler(const struct mg_connection * conn, void * _
64616491
if (_webui_core.exit_now || win == NULL)
64626492
return 1;
64636493

6464-
if (win->connected) {
6494+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
64656495

64666496
// Non-authorized connection
64676497
#ifdef WEBUI_LOG
@@ -6535,7 +6565,7 @@ static void _webui_ws_close_handler(const struct mg_connection * conn, void * _w
65356565

65366566
// Dereference
65376567
_webui_window_t * win = _webui_dereference_win_ptr(_win);
6538-
if (_webui_core.exit_now || win == NULL || !win->connected)
6568+
if (_webui_core.exit_now || win == NULL || !_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
65396569
return;
65406570

65416571
_webui_receive(win, WEBUI_WS_CLOSE, (void * ) conn, 0);
@@ -6705,7 +6735,7 @@ static WEBUI_THREAD_SERVER_START {
67056735

67066736
while(!stop) {
67076737

6708-
if (!win->connected) {
6738+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
67096739

67106740
#ifdef WEBUI_LOG
67116741
printf(
@@ -6722,7 +6752,7 @@ static WEBUI_THREAD_SERVER_START {
67226752

67236753
// Stop if window is connected
67246754
_webui_sleep(1);
6725-
if (win->connected || win->server_handled)
6755+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE) || win->server_handled)
67266756
break;
67276757

67286758
// Stop if timer is finished
@@ -6731,7 +6761,7 @@ static WEBUI_THREAD_SERVER_START {
67316761
break;
67326762
}
67336763

6734-
if (!win->connected && win->server_handled) {
6764+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE) && win->server_handled) {
67356765

67366766
// At this moment the browser is already started and HTML
67376767
// is already handled, so, let's wait more time to give
@@ -6755,17 +6785,17 @@ static WEBUI_THREAD_SERVER_START {
67556785

67566786
// Stop if window is connected
67576787
_webui_sleep(1);
6758-
if (win->connected)
6788+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
67596789
break;
67606790

67616791
// Stop if timer is finished
67626792
if (_webui_timer_is_end( & timer_2, 3000))
67636793
break;
67646794
}
6765-
} while(win->file_handled && !win->connected);
6795+
} while(win->file_handled && !_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE));
67666796
}
67676797

6768-
if (!win->connected)
6798+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
67696799
stop = true; // First run failed
67706800
} else {
67716801

@@ -6790,7 +6820,7 @@ static WEBUI_THREAD_SERVER_START {
67906820
break;
67916821
}
67926822

6793-
if (!win->connected && !_webui_core.exit_now) {
6823+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE) && !_webui_core.exit_now) {
67946824

67956825
// The UI is just get disconnected
67966826
// probably the user did a refresh
@@ -6821,16 +6851,16 @@ static WEBUI_THREAD_SERVER_START {
68216851

68226852
// Stop if window is re-connected
68236853
_webui_sleep(1);
6824-
if (win->connected)
6854+
if (_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE))
68256855
break;
68266856

68276857
// Stop if timer is finished
68286858
if (_webui_timer_is_end( & timer_3, 1000))
68296859
break;
68306860
}
6831-
} while(win->file_handled && !win->connected);
6861+
} while(win->file_handled && !_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE));
68326862

6833-
if (!win->connected) {
6863+
if (!_webui_mtx_is_connected(win, WEBUI_MUTEX_NONE)) {
68346864
stop = true;
68356865
break;
68366866
}
@@ -6877,7 +6907,7 @@ static WEBUI_THREAD_SERVER_START {
68776907
win->html_handled = false;
68786908
win->server_handled = false;
68796909
win->bridge_handled = false;
6880-
win->connected = false;
6910+
_webui_mtx_is_connected(win, WEBUI_MUTEX_FALSE);
68816911
_webui_free_port(win->server_port);
68826912
_webui_free_port(win->ws_port);
68836913
win->server_port = 0;
@@ -7483,7 +7513,7 @@ static WEBUI_THREAD_RECEIVE {
74837513
#endif
74847514

74857515
// Forced close
7486-
win->connected = false;
7516+
_webui_mtx_is_connected(win, WEBUI_MUTEX_FALSE);
74877517
}
74887518
} else if (event_type == WEBUI_WS_OPEN) {
74897519

@@ -7492,7 +7522,7 @@ static WEBUI_THREAD_RECEIVE {
74927522
struct mg_connection * conn = (struct mg_connection * ) ptr;
74937523

74947524
// First connection
7495-
win->connected = true; // server thread
7525+
_webui_mtx_is_connected(win, WEBUI_MUTEX_TRUE); // server thread
74967526
event_user = WEBUI_EVENT_CONNECTED; // User event
74977527
win->mg_connection = conn; // send
74987528

@@ -7536,7 +7566,7 @@ static WEBUI_THREAD_RECEIVE {
75367566
} else if (event_type == WEBUI_WS_CLOSE) {
75377567

75387568
// Main connection close
7539-
win->connected = false;
7569+
_webui_mtx_is_connected(win, WEBUI_MUTEX_FALSE);
75407570
win->html_handled = false;
75417571
win->server_handled = false;
75427572
win->bridge_handled = false;

0 commit comments

Comments
 (0)