From patchwork Sat Jun 15 19:11:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Glembotzki X-Patchwork-Id: 1948218 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=googlegroups.com header.i=@googlegroups.com header.a=rsa-sha256 header.s=20230601 header.b=hIWv+oKJ; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=XIyk/y+j; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=googlegroups.com (client-ip=2a00:1450:4864:20::63b; helo=mail-ej1-x63b.google.com; envelope-from=swupdate+bncbdy5juxlviebba6tw6zqmgqe3wdeh7i@googlegroups.com; receiver=patchwork.ozlabs.org) Received: from mail-ej1-x63b.google.com (mail-ej1-x63b.google.com [IPv6:2a00:1450:4864:20::63b]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W1mFg3gwnz20Pb for ; Sun, 16 Jun 2024 05:20:39 +1000 (AEST) Received: by mail-ej1-x63b.google.com with SMTP id a640c23a62f3a-a6f0f008f9asf95328966b.3 for ; Sat, 15 Jun 2024 12:20:39 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1718479236; cv=pass; d=google.com; s=arc-20160816; b=VVR1QckFIEWanTOYSfhNOnJEIeOy6/dRi3k74NdyIB5THu+QHB7kgAdFKHTYUuVHZu qMKAOEsmTDHKGrv+QNh4V/cezJPPfKQVWy8BejNJhQ5CMPbdPpId1w4kVBSDyFbfiUka R5Q1j12etV1xiQL9b5RgiJASLQj9PB7/g10YHuMFS22/NqtrF5xsBThPZ/tPBcP8Dnpc 718uB8nVEB5VaxktxqgDFMOXfE9avIYfZg7XCbzAjWTGeMxecAbzUafGoNSHqBftfejy 1+olt9H+R/pX1FBNk5qWNdle+Lo9JIgLTf0dwzjst7CBUoaHlu/4LOcCVOjvDBBKwfK1 UAew== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:sender:dkim-signature :dkim-signature; bh=Damtbiy8JYAwqZ4f0J69EeHu41hyQtnoiTwpc1T86HY=; fh=8j7+QGzOea9910WMwYM3UzYnDPcyaHVXq2aOMuTdeZw=; b=v3kzjph2bw8BYbww+cunnqgBrY0SLRJ3KUmOTEr5bZegEjW6mPuUKXX4UtT+Ucm9VA 7BQVMom065EC5pD004psgz4v4UBBhVuO0JNlbRUJr6UmRdpM31u8eORa6ztUOThOkDXR yQl+cOnp3tI/5ClXkxIK7Ur1hN++QFNNVvp2NO93u/gaeuYwQepMyDvm3mV/OC/cJAsZ NrwB+k5OlTPM4NuFbKghzq7eq5Clpqrbn2kBxltd58W0n5aQFOo1pjvXun8HWeRyxfgx VNJzvhpyMu6LWhNTe8zbjuX3JkcGg6nsza+CnIYdj/KQkZhzPTQ8x6Hsn9YONBcdLlch 8onQ==; darn=patchwork.ozlabs.org ARC-Authentication-Results: i=2; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=cTfAhYjv; spf=pass (google.com: domain of m.glembo@gmail.com designates 2a00:1450:4864:20::12f as permitted sender) smtp.mailfrom=m.glembo@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=20230601; t=1718479236; x=1719084036; darn=patchwork.ozlabs.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:sender:from:to:cc:subject:date:message-id :reply-to; bh=Damtbiy8JYAwqZ4f0J69EeHu41hyQtnoiTwpc1T86HY=; b=hIWv+oKJOafkBt/a8vpmaCX6Ej9R5FWEZRwgxhUCaHPkSa6NuqJrAsR+VT/7t6qF/+ DVkredFDoGHD/Zzq1NYkf5yHshiriS8def+L6nt28durCXR/CuUZ+KrrIhH06X4Bx4Lm oEFKEUd0H0rBSmS1qKkzWHb32iMiC/DOenA/8yfbj3NyOJKo3ADNlhFtP/D4O0hg6DpP zyg3HA1FTfUXF0ss+43e7iyrIPJ1Z7f44RDapnkTbAASaMlr/NeTix9SMSnP1kgZyMoh yDUouTMSXbpj914zAjBFFxs2Dbh7ts3U+mYQsI+DmxuYgq6tikbnWQmhJb2Nj6EnRJQD oogQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1718479236; x=1719084036; darn=patchwork.ozlabs.org; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :list-id:mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=Damtbiy8JYAwqZ4f0J69EeHu41hyQtnoiTwpc1T86HY=; b=XIyk/y+jcvF5TYXPz1kU4y3z/DGwF7vuEkYk8pMt/DjJIyzaPQbl33kAJaLclcy5JF PHdKduTbQxkJX/vpJpXY1HLryxqUfZYJ/mYwgtlMgPWXJ4ecfNF8dK3Nwx0A6D0RZpQu j0Yo3uO2zCE4hWybwK+q3rAzQcZu1v9AZmKHCoExpOEwMeZ4SRxVQ7Alqd2nFRKxS99n tzTqInQBCS1P+TPPUJm31v0tq9ciLBs6AhD7uQzcwtkqOC2OprZ6AEi5XjXmxj8rMoH3 Fyrd+g9MKAJdY1/n8TLkr+O9tJxFn+jv0aouFyFMevYgJP4OLxE1WMBagBB13XluLqK9 RQ1A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718479236; x=1719084036; h=list-unsubscribe:list-subscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :x-beenthere:x-gm-message-state:sender:from:to:cc:subject:date :message-id:reply-to; bh=Damtbiy8JYAwqZ4f0J69EeHu41hyQtnoiTwpc1T86HY=; b=Jlx4HzYkjWO4JjyCE7qH5hS74gU580XzlNlWhfdn1QpPOPAiIi2Pnp7JlQzUlCXQ2c jfc7pJzTldaEUpaYp9Am5zTowmmJA87nzIB9j3U17R0W3cJJBYUkUHNEPag2gv+d3Y8H 9j833dQqjCOdGZW+Wyc3uRclMovOtquvxcIMGmx92+EbrV5B9xBJp4ooyY73YK45TzHd sH00lBAV13boVnQS8HZL7gO4ERbmKyGdf/R47E6yJsajGmHPmt2gvIs8ruyUSXSJNhsr RFb1/XVZ5nN69QT4rit4yAxvkL+7LCpoUtjX2PzYUCa7XQQqXKCGj/oMsAHoQ4W/1sM+ abfQ== Sender: swupdate@googlegroups.com X-Forwarded-Encrypted: i=2; AJvYcCVDc3sNpCEge+PvmP2LSpo5LfcRHc8lJ02+kYk8FHtVhlDRpoKCqTphDwi0WHjHFlwWNaWJjAqQdxSMaPOoN6PThSuWlu8Y5K+cBKOWcA== X-Gm-Message-State: AOJu0Yy2kT1GRyT4Dk7Umij7eXPblqNxg9GuR6OCbD3l2kR/EQ+u6mJ/ z2ffMsjFDnjgBRYqPh1+XnDErYwLaSyghhxr5VhWeTo/4A5Xan7k X-Google-Smtp-Source: AGHT+IFpgB2CkT83ZUcMnVdiGbtYpfxKxxEemYPYXv6gTAMLuZaYfdWOWUBPpRGIC4bGEK1ICfrBAw== X-Received: by 2002:aa7:d487:0:b0:57c:d228:772f with SMTP id 4fb4d7f45d1cf-57cd2287a42mr1318259a12.10.1718479235918; Sat, 15 Jun 2024 12:20:35 -0700 (PDT) X-BeenThere: swupdate@googlegroups.com Received: by 2002:a05:6402:27d3:b0:57c:a472:931c with SMTP id 4fb4d7f45d1cf-57cb4a604bcls625768a12.0.-pod-prod-05-eu; Sat, 15 Jun 2024 12:20:33 -0700 (PDT) X-Received: by 2002:a50:ab17:0:b0:57c:70be:6558 with SMTP id 4fb4d7f45d1cf-57cbd6c7462mr4410742a12.27.1718479233337; Sat, 15 Jun 2024 12:20:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1718479233; cv=none; d=google.com; s=arc-20160816; b=LuVoUtJRaZZFw/O9dS9rwSWcsuCL5ajXY4T6zH0y+0pEN0b6cRQbIIhMnzC/W+WFdd KdSNR0EWM1X8/TExMlwHn0p2jt8iEgawgtRlG+abR0azD1lwfWhi4RONE9kbI3LBi+s9 Ekyw2kWmyxZFST9Ip/+NaV7XMvcvjVxk20t+RpMRfBaKw42aZVdaO6oBr9jFH3L632EV cD3grqcDISU7o7kz7P5J2twtCUI1W0txbeEVFD2kUnN/EB4Aiw55xO6qKx8cPtEyIqvd Ux5IO5Y4QRfYPT8Nw5flcQ1QOSEZ48JURX7lgYWs3S1R76VigVK8szvAMl+OTUO6wgfE ZHvw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=YZmRABg+UkVVbVBxe0e71B7g6gbZnSz/4Y2W10Lfsuk=; fh=zydHuzCQWrku2OPQyZfraJZFcOpEXLQ/YBcu3QNiBd0=; b=GYZ9hgir4iucfEFaWlItpNwshbNgeZMjNcJYCCS5XQH1Onj3xcOYKreMAO8S4F1Mb2 fPfwXeA2z44nnDHMrtYG8bZej7dfPDyRsb8TH1mdS0EKxKEQkt3kCKpW14LDZKbPV8pb XV3Ud2j4WhkgeoDTbk1QZkANzp1t2ZOIlP/UmuIldi0/HaUeIiXtXI6ANTvx8h+4JKiR cxEmMxA0O8rVFUbZ+FWE54Aij655phHI+BG5QdfCuWoS2/05t1iWOiR+Rhu3iIV0HUdk vHsmY8fvOWVMAmZC9hxEdKt/EOoeRkZCb2NWLK9ru7tNmSUfJlG2GnYHC5/jdNs6BbLv voPw==; dara=google.com ARC-Authentication-Results: i=1; gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=cTfAhYjv; spf=pass (google.com: domain of m.glembo@gmail.com designates 2a00:1450:4864:20::12f as permitted sender) smtp.mailfrom=m.glembo@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from mail-lf1-x12f.google.com (mail-lf1-x12f.google.com. [2a00:1450:4864:20::12f]) by gmr-mx.google.com with ESMTPS id 4fb4d7f45d1cf-57cb7449f1csi133552a12.4.2024.06.15.12.20.33 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 15 Jun 2024 12:20:33 -0700 (PDT) Received-SPF: pass (google.com: domain of m.glembo@gmail.com designates 2a00:1450:4864:20::12f as permitted sender) client-ip=2a00:1450:4864:20::12f; Received: by mail-lf1-x12f.google.com with SMTP id 2adb3069b0e04-52c9034860dso4080692e87.2 for ; Sat, 15 Jun 2024 12:20:33 -0700 (PDT) X-Received: by 2002:a19:9142:0:b0:52c:999b:5306 with SMTP id 2adb3069b0e04-52ca6e6717amr4588892e87.17.1718479232247; Sat, 15 Jun 2024 12:20:32 -0700 (PDT) Received: from PC-2635.irisgmbh.local ([2a02:8108:96c0:76fc::80bb]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a6f56db61e0sm327283766b.49.2024.06.15.12.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 15 Jun 2024 12:20:31 -0700 (PDT) From: Michael Glembotzki To: swupdate@googlegroups.com Cc: Michael Glembotzki Subject: [swupdate] [PATCH 21/21] mongoose: Replace deprecated mg_mkpipe() with mg_wakeup() Date: Sat, 15 Jun 2024 21:11:34 +0200 Message-ID: <20240615191941.40301-22-Michael.Glembotzki@iris-sensing.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240615191941.40301-1-Michael.Glembotzki@iris-sensing.com> References: <20240615191941.40301-1-Michael.Glembotzki@iris-sensing.com> MIME-Version: 1.0 X-Original-Sender: m.glembo@gmail.com X-Original-Authentication-Results: gmr-mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=cTfAhYjv; spf=pass (google.com: domain of m.glembo@gmail.com designates 2a00:1450:4864:20::12f as permitted sender) smtp.mailfrom=m.glembo@gmail.com; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Precedence: list Mailing-list: list swupdate@googlegroups.com; contact swupdate+owners@googlegroups.com List-ID: X-Spam-Checked-In-Group: swupdate@googlegroups.com X-Google-Group-Id: 605343134186 List-Post: , List-Help: , List-Archive: , List-Unsubscribe: , Use the new mg_wakeup() [1] mechansim to send data from the broadcast(s) to the parent event manager thread. Based on mongoose multi-threaded example [2]. [1] https://mongoose.ws/documentation/#mg_wakeup [2] https://github.com/cesanta/mongoose/blob/master/tutorials/core/multi-threaded-12m/main.c Signed-off-by: Michael Glembotzki --- mongoose/mongoose_interface.c | 104 ++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 43 deletions(-) diff --git a/mongoose/mongoose_interface.c b/mongoose/mongoose_interface.c index f67b1089..260ed8f9 100644 --- a/mongoose/mongoose_interface.c +++ b/mongoose/mongoose_interface.c @@ -64,6 +64,11 @@ struct file_upload_state { uint64_t last_io_time; }; +struct parent_connection_info { + struct mg_mgr *mgr; + unsigned long conn_id; +}; + static bool run_postupdate; static unsigned int watchdog_conn = 0; static struct mg_http_serve_opts s_http_server_opts; @@ -74,8 +79,6 @@ static bool ssl; static struct mg_tls_opts tls_opts; #endif -static int ws_pipe; - static int s_signo = 0; static void signal_handler(int signo) { s_signo = signo; @@ -358,30 +361,6 @@ static void restart_handler(struct mg_connection *nc, void *ev_data) mg_http_reply(nc, 201, "", "%s", "Device will reboot now.\n"); } -static void broadcast_callback(struct mg_connection *nc, int ev, - void __attribute__ ((__unused__)) *ev_data) -{ - static uint64_t last_io_time = 0; - if (ev == MG_EV_READ) { - struct mg_connection *t; - for (t = nc->mgr->conns; t != NULL; t = t->next) { - if (!t->is_websocket) continue; - mg_ws_send(t,(char *)nc->recv.buf, nc->recv.len, WEBSOCKET_OP_TEXT); - } - mg_iobuf_del(&nc->recv, 0, nc->recv.len); - last_io_time = mg_millis(); - } else if (ev == MG_EV_POLL) { - struct mg_connection *t; - uint64_t now = *((uint64_t *)ev_data); - if (now < last_io_time + 20000) return; - for (t = nc->mgr->conns; t != NULL; t = t->next) { - if (!t->is_websocket) continue; - mg_ws_send(t, "", 0, WEBSOCKET_OP_PING); - } - last_io_time = now; - } -} - static int level_to_rfc_5424(int level) { switch(level) { @@ -398,14 +377,18 @@ static int level_to_rfc_5424(int level) } } -static void broadcast(char *str) +static void broadcast(struct parent_connection_info *p, char *str) { - send(ws_pipe, str, strlen(str), 0); + mg_wakeup(p->mgr, p->conn_id, str, strlen(str)); } -static void *broadcast_message_thread(void __attribute__ ((__unused__)) *data) +static void *broadcast_message_thread(void *data) { int fd = -1; + struct parent_connection_info *p = (struct parent_connection_info *) data; + + if(!p) + return NULL; for (;;) { ipc_message msg; @@ -423,7 +406,7 @@ static void *broadcast_message_thread(void __attribute__ ((__unused__)) *data) ret = ipc_notify_receive(&fd, &msg); if (ret != sizeof(msg)) - return NULL; + break; if (strlen(msg.data.notify.msg) != 0 && msg.data.status.current != PROGRESS) { @@ -441,18 +424,24 @@ static void *broadcast_message_thread(void __attribute__ ((__unused__)) *data) level_to_rfc_5424(msg.data.notify.level), /* RFC 5424 */ text); - broadcast(str); + broadcast(p, str); } } + free(p); + return NULL; } -static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) +static void *broadcast_progress_thread(void *data) { RECOVERY_STATUS status = -1; sourcetype source = -1; unsigned int step = 0; uint8_t percent = 0; int fd = -1; + struct parent_connection_info *p = (struct parent_connection_info *) data; + + if(!p) + return NULL; for (;;) { struct progress_msg msg; @@ -472,7 +461,7 @@ static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) ret = progress_ipc_receive(&fd, &msg); if (ret != sizeof(msg)) - return NULL; + break; if (msg.status != PROGRESS && (msg.status != status || msg.status == FAILURE)) { @@ -486,7 +475,7 @@ static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) "\t\"status\": \"%s\"\r\n" "}\r\n", escaped); - broadcast(str); + broadcast(p, str); } if (msg.source != source) { @@ -498,7 +487,7 @@ static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) "\t\"source\": \"%s\"\r\n" "}\r\n", get_source_string(msg.source)); - broadcast(str); + broadcast(p, str); } if (msg.status == SUCCESS && msg.source == SOURCE_WEBSERVER && run_postupdate) { @@ -516,7 +505,7 @@ static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) "\t\"source\": \"%s\"\r\n" "}\r\n", escaped); - broadcast(str); + broadcast(p, str); } if ((msg.cur_step != step || msg.cur_percent != percent) && @@ -538,9 +527,11 @@ static void *broadcast_progress_thread(void __attribute__ ((__unused__)) *data) msg.cur_step, escaped, msg.cur_percent); - broadcast(str); + broadcast(p, str); } } + free(p); + return NULL; } static void timer_ev_handler(void *fn_data) @@ -682,11 +673,20 @@ static void websocket_handler(struct mg_connection *nc, void *ev_data) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; mg_ws_upgrade(nc, hm, NULL); + nc->data[0] = 'W'; // Set unique Websocket marker } static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { - if (nc->data[0] != 'M' && ev == MG_EV_HTTP_MSG) { + static uint64_t last_io_time = 0; + if (ev == MG_EV_OPEN && nc->is_listening) { + struct parent_connection_info *data = calloc(2, sizeof(struct parent_connection_info)); + data[0].mgr = nc->mgr; + data[0].conn_id = nc->id; + memcpy(&data[1], &data[0], sizeof(struct parent_connection_info)); + start_thread(broadcast_message_thread, &data[0]); + start_thread(broadcast_progress_thread, &data[1]); + } else if (nc->data[0] != 'M' && nc->data[0] != 'W' && ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; if (!mg_http_is_authorized(hm, global_auth_domain, global_auth_file)) mg_http_send_digest_auth_request(nc, global_auth_domain); @@ -696,7 +696,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) restart_handler(nc, ev_data); else mg_http_serve_dir(nc, ev_data, &s_http_server_opts); - } else if (nc->data[0] != 'M' && ev == MG_EV_READ) { + } else if (nc->data[0] != 'M' && nc->data[0] != 'W' && ev == MG_EV_READ) { struct mg_http_message hm; int hlen = mg_http_parse((char *) nc->recv.buf, nc->recv.len, &hm); if (hlen > 0) { @@ -727,6 +727,27 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) ERROR("%p %s", nc->fd, (char *) ev_data); } else if (ev == MG_EV_WS_MSG) { mg_iobuf_del(&nc->recv, 0, nc->recv.len); + } else if (ev == MG_EV_WAKEUP) { + // forward broadcast messages + struct mg_str *data = (struct mg_str *) ev_data; + struct mg_connection *t; + for (t = nc->mgr->conns; t != NULL; t = t->next) { + if (t->data[0] == 'W') { + mg_ws_send(t, data->buf, data->len, WEBSOCKET_OP_TEXT); + } + } + last_io_time = mg_millis(); + } else if (ev == MG_EV_POLL) { + // websocket heartbeat every 20s + struct mg_connection *t; + uint64_t now = *((uint64_t *)ev_data); + if (now < last_io_time + 20000) return; + for (t = nc->mgr->conns; t != NULL; t = t->next) { + if (t->data[0] == 'W') { + mg_ws_send(t, "", 0, WEBSOCKET_OP_PING); + } + } + last_io_time = now; } } @@ -908,8 +929,6 @@ int start_mongoose(const char *cfgfname, int argc, char *argv[]) signal(SIGTERM, signal_handler); mg_mgr_init(&mgr); - ws_pipe = mg_mkpipe(&mgr, broadcast_callback, NULL, true); - /* Parse url with port only fallback */ if (opts.port) { if (mg_url_port(opts.port) != 0) { @@ -934,8 +953,7 @@ int start_mongoose(const char *cfgfname, int argc, char *argv[]) exit(EXIT_FAILURE); } - start_thread(broadcast_message_thread, NULL); - start_thread(broadcast_progress_thread, NULL); + mg_wakeup_init(&mgr); INFO("Mongoose web server v%s with PID %d listening on %s and serving %s", MG_VERSION, getpid(), url, s_http_server_opts.root_dir);