From 76cbff370efa8e5d08b2f10e45b58710e6afeb2d Mon Sep 17 00:00:00 2001 From: Tony <68118705+Legend-Master@users.noreply.github.com> Date: Sun, 18 Jun 2023 15:58:49 +0800 Subject: [PATCH 1/2] Fix purgeable is always false on supernode peer list (#1117) * Fix purgeable is always false on sn peer list - And change sn_purge to bool * Change all keep_on_running to bool * Fix wrong `keep_running` type --- include/n2n.h | 4 ++-- include/n2n_define.h | 3 --- include/n2n_typedefs.h | 11 ++++++----- src/edge.c | 5 ++--- src/edge_management.c | 4 ++-- src/edge_utils.c | 16 ++++++++-------- src/example_edge_embed.c | 7 +++---- src/example_edge_embed_quick_edge_init.c | 2 +- src/example_sn_embed.c | 3 +-- src/management.c | 2 +- src/management.h | 2 +- src/n2n.c | 8 ++++---- src/sn_management.c | 4 ++-- src/sn_utils.c | 13 +++++++------ src/supernode.c | 9 ++++----- tools/n2n-portfwd.c | 4 ++-- tools/n2n-route.c | 12 ++++++------ 17 files changed, 52 insertions(+), 57 deletions(-) diff --git a/include/n2n.h b/include/n2n.h index c798722..a81612c 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -50,7 +50,7 @@ #endif - +#include #include #include #include @@ -272,7 +272,7 @@ int quick_edge_init (char *device_name, char *community_name, char *encrypt_key, char *device_mac, char *local_ip_address, char *supernode_ip_address_port, - int *keep_on_running); + bool *keep_on_running); int comm_init (struct sn_community *comm, char *cmn); int sn_init_defaults (n2n_sn_t *sss); void sn_init (n2n_sn_t *sss); diff --git a/include/n2n_define.h b/include/n2n_define.h index 230df6f..27113b9 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -99,9 +99,6 @@ #define FEDERATION_NAME "*Federation" enum federation {IS_NO_FEDERATION = 0,IS_FEDERATION = 1}; -/* (un)purgeable indicator for supernodes, communities, routes, ... */ -enum sn_purge {UNPURGEABLE = 0, PURGEABLE = 1}; - /* Header encryption indicators */ #define HEADER_ENCRYPTION_UNKNOWN 0 #define HEADER_ENCRYPTION_NONE 1 diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index ad76fd6..582b590 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -19,6 +19,7 @@ #ifndef _N2N_TYPEDEFS_H_ #define _N2N_TYPEDEFS_H_ +#include #include // for uint8_t and friends #ifndef WIN32 #include // for in_addr_t @@ -455,7 +456,7 @@ struct peer_info { n2n_cookie_t last_cookie; n2n_auth_t auth; int timeout; - uint8_t purgeable; + bool purgeable; time_t last_seen; time_t last_p2p; time_t last_sent_query; @@ -703,7 +704,7 @@ struct n2n_edge { n2n_edge_conf_t conf; /* Status */ - int *keep_running; /**< Pointer to edge loop stop/go flag */ + bool *keep_running; /**< Pointer to edge loop stop/go flag */ struct peer_info *curr_sn; /**< Currently active supernode. */ uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */ uint8_t sn_pong; /**< Whether we have seen a PONG since last time reset. */ @@ -733,7 +734,7 @@ struct n2n_edge { /* Peers */ struct peer_info * known_peers; /**< Edges we are connected to. */ struct peer_info * pending_peers; /**< Edges we have tried to register with. */ -#ifdef HAVE_BRIDGING_SUPPORT +#ifdef HAVE_BRIDGING_SUPPORT struct host_info * known_hosts; /**< hosts we know. */ #endif /* Timers */ @@ -789,7 +790,7 @@ typedef struct sn_user { struct sn_community { char community[N2N_COMMUNITY_SIZE]; uint8_t is_federation; /* if not-zero, then the current community is the federation of supernodes */ - uint8_t purgeable; /* indicates purgeable community (fixed-name, predetermined (-c parameter) communties usually are unpurgeable) */ + bool purgeable; /* indicates purgeable community (fixed-name, predetermined (-c parameter) communties usually are unpurgeable) */ uint8_t header_encryption; /* Header encryption indicator. */ he_context_t *header_encryption_ctx_static; /* Header encryption cipher context. */ he_context_t *header_encryption_ctx_dynamic; /* Header encryption cipher context. */ @@ -832,7 +833,7 @@ typedef struct n2n_tcp_connection { typedef struct n2n_sn { - int *keep_running; /* Pointer to sn loop stop/go flag */ + bool *keep_running; /* Pointer to sn loop stop/go flag */ time_t start_time; /* Used to measure uptime. */ n2n_version_t version; /* version string sent to edges along with PEER_INFO a.k.a. PONG */ sn_stats_t stats; diff --git a/src/edge.c b/src/edge.c index 33040a3..8bbf162 100644 --- a/src/edge.c +++ b/src/edge.c @@ -925,7 +925,7 @@ static void daemonize () { /* *************************************************** */ -static int keep_on_running; +static bool keep_on_running = true; #if defined(__linux__) || defined(WIN32) #ifdef WIN32 @@ -944,7 +944,7 @@ BOOL WINAPI term_handler(DWORD sig) called = 1; } - keep_on_running = 0; + keep_on_running = false; #ifdef WIN32 return(TRUE); #endif @@ -1303,7 +1303,6 @@ int main (int argc, char* argv[]) { SetConsoleCtrlHandler(term_handler, TRUE); #endif - keep_on_running = 1; eee->keep_running = &keep_on_running; traceEvent(TRACE_NORMAL, "edge started"); rc = run_edge_loop(eee); diff --git a/src/edge_management.c b/src/edge_management.c index 42b78fa..ed329d5 100644 --- a/src/edge_management.c +++ b/src/edge_management.c @@ -472,7 +472,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) { if(0 == memcmp(udp_buf, "stop", 4)) { traceEvent(TRACE_NORMAL, "stop command received"); - *eee->keep_running = 0; + *eee->keep_running = false; return; } @@ -586,7 +586,7 @@ void readFromMgmtSocket (n2n_edge_t *eee) { msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "%-19s %1s%1s | %-17s | %-21s | %-15s | %9s | %10s\n", peer->version, - (peer->purgeable == UNPURGEABLE) ? "l" : "", + (peer->purgeable == false) ? "l" : "", (peer == eee->curr_sn) ? (eee->sn_wait ? "." : "*" ) : "", is_null_mac(peer->mac_addr) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), diff --git a/src/edge_utils.c b/src/edge_utils.c index 378376d..2dd888b 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -2863,7 +2863,7 @@ int run_edge_loop (n2n_edge_t *eee) { HANDLE tun_read_thread = startTunReadThread(&arg); #endif - *eee->keep_running = 1; + *eee->keep_running = true; update_supernode_reg(eee, time(NULL)); /* Main loop @@ -2922,7 +2922,7 @@ int run_edge_loop (n2n_edge_t *eee) { if(0 != fetch_and_eventually_process_data(eee, eee->sock, pktbuf, &expected, &position, now)) { - *eee->keep_running = 0; + *eee->keep_running = false; break; } if(eee->conf.connect_tcp) { @@ -2943,7 +2943,7 @@ int run_edge_loop (n2n_edge_t *eee) { if(0 != fetch_and_eventually_process_data(eee, eee->udp_multicast_sock, pktbuf, &expected, &position, now)) { - *eee->keep_running = 0; + *eee->keep_running = false; break; } } @@ -2991,7 +2991,7 @@ int run_edge_loop (n2n_edge_t *eee) { if((eee->conf.allow_routing) && (now > last_purge_host + SWEEP_TIME)) { struct host_info *host, *host_tmp; HASH_ITER(hh, eee->known_hosts, host, host_tmp) { - if(now > host->last_seen + HOSTINFO_TIMEOUT) { + if(now > host->last_seen + HOSTINFO_TIMEOUT) { HASH_DEL(eee->known_hosts, host); free(host); } @@ -3057,12 +3057,12 @@ void edge_term (n2n_edge_t * eee) { #ifdef HAVE_BRIDGING_SUPPORT if(eee->conf.allow_routing) { struct host_info *host, *host_tmp; - HASH_ITER(hh, eee->known_hosts, host, host_tmp) { + HASH_ITER(hh, eee->known_hosts, host, host_tmp) { HASH_DEL(eee->known_hosts, host); free(host); } } -#endif +#endif eee->transop.deinit(&eee->transop); eee->transop_lzo.deinit(&eee->transop_lzo); @@ -3223,7 +3223,7 @@ int edge_conf_add_supernode (n2n_edge_conf_t *conf, const char *ip_and_port) { strncpy(sn->ip_addr, ip_and_port, N2N_EDGE_SN_HOST_SIZE - 1); memcpy(&(sn->sock), sock, sizeof(n2n_sock_t)); memcpy(sn->mac_addr, null_mac, sizeof(n2n_mac_t)); - sn->purgeable = UNPURGEABLE; + sn->purgeable = false; } } @@ -3241,7 +3241,7 @@ int quick_edge_init (char *device_name, char *community_name, char *encrypt_key, char *device_mac, char *local_ip_address, char *supernode_ip_address_port, - int *keep_on_running) { + bool *keep_on_running) { tuntap_dev tuntap; n2n_edge_t *eee; diff --git a/src/example_edge_embed.c b/src/example_edge_embed.c index 76388b7..2784d78 100644 --- a/src/example_edge_embed.c +++ b/src/example_edge_embed.c @@ -18,7 +18,7 @@ #include "n2n.h" -static int keep_running; +static bool keep_running = true; int main() { @@ -56,8 +56,8 @@ int main() { DEFAULT_MTU // MTU to use #ifdef WIN32 , 0 -#endif - ) < 0) +#endif + ) < 0) { return -1; } @@ -67,7 +67,6 @@ int main() { exit(1); } - keep_running = 1; eee->keep_running = &keep_running; rc = run_edge_loop(eee); diff --git a/src/example_edge_embed_quick_edge_init.c b/src/example_edge_embed_quick_edge_init.c index e96a765..65da193 100644 --- a/src/example_edge_embed_quick_edge_init.c +++ b/src/example_edge_embed_quick_edge_init.c @@ -31,7 +31,7 @@ int main (int argc, char* argv[]) { char *my_mac_address = (char*)"DE:AD:BE:EF:01:10"; char *my_ipv4_addr = (char*)"1.2.3.4"; char *supernode = (char*)"7.8.9.10:1234"; - int keep_on_running = 1; + bool keep_on_running = true; /* Increase tracelevel to see what's happening */ setTraceLevel(10); diff --git a/src/example_sn_embed.c b/src/example_sn_embed.c index dc1ed18..52356be 100644 --- a/src/example_sn_embed.c +++ b/src/example_sn_embed.c @@ -18,7 +18,7 @@ #include "n2n.h" -static int keep_running; +static bool keep_running = true; int main () { @@ -41,7 +41,6 @@ int main () { sn_init(&sss_node); - keep_running = 1; sss_node.keep_running = &keep_running; rc = run_sn_loop(&sss_node); diff --git a/src/management.c b/src/management.c index 5a27dcf..73da48a 100644 --- a/src/management.c +++ b/src/management.c @@ -65,7 +65,7 @@ void mgmt_error (mgmt_req_t *req, strbuf_t *buf, char *msg) { void mgmt_stop (mgmt_req_t *req, strbuf_t *buf) { if(req->type==N2N_MGMT_WRITE) { - *req->keep_running = 0; + *req->keep_running = false; } send_json_1uint(req, buf, "row", "keep_running", *req->keep_running); diff --git a/src/management.h b/src/management.h index 3dc542d..9932df1 100644 --- a/src/management.h +++ b/src/management.h @@ -33,7 +33,7 @@ typedef struct mgmt_req { n2n_sn_t *sss; n2n_edge_t *eee; int mgmt_sock; // socket replies come from - int *keep_running; + bool *keep_running; uint64_t mgmt_password_hash; enum n2n_mgmt_type type; char *argv0; diff --git a/src/n2n.c b/src/n2n.c index c6a7ace..99d2a26 100644 --- a/src/n2n.c +++ b/src/n2n.c @@ -425,13 +425,13 @@ uint8_t resolve_check (n2n_resolve_parameter_t *param, uint8_t requires_resoluti uint8_t ret = requires_resolution; /* if trylock fails, it still requires resolution */ -#ifdef HAVE_PTHREAD +#ifdef HAVE_PTHREAD n2n_resolve_ip_sock_t *entry, *tmp_entry; n2n_sock_str_t sock_buf; if(NULL == param) return ret; - + // check_interval and last_check do not need to be guarded by the mutex because // their values get changed and evaluated only here @@ -635,7 +635,7 @@ size_t purge_peer_list (struct peer_info **peer_list, size_t retval = 0; HASH_ITER(hh, *peer_list, scan, tmp) { - if((scan->purgeable == PURGEABLE) && (scan->last_seen < purge_before)) { + if(scan->purgeable && scan->last_seen < purge_before) { if((scan->socket_fd >=0) && (scan->socket_fd != socket_not_to_close)) { if(tcp_connections) { HASH_FIND_INT(*tcp_connections, &scan->socket_fd, conn); @@ -665,7 +665,7 @@ size_t clear_peer_list (struct peer_info ** peer_list) { size_t retval = 0; HASH_ITER(hh, *peer_list, scan, tmp) { - if (scan->purgeable == UNPURGEABLE && scan->ip_addr) { + if (scan->purgeable == false && scan->ip_addr) { free(scan->ip_addr); } HASH_DEL(*peer_list, scan); diff --git a/src/sn_management.c b/src/sn_management.c index 61c94b9..b84db5a 100644 --- a/src/sn_management.c +++ b/src/sn_management.c @@ -356,7 +356,7 @@ int process_mgmt (n2n_sn_t *sss, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "%s '%s'\n", - (community->is_federation) ? "FEDERATION" : ((community->purgeable == UNPURGEABLE) ? "FIXED NAME COMMUNITY" : "COMMUNITY"), + (community->is_federation) ? "FEDERATION" : ((community->purgeable == false) ? "FIXED NAME COMMUNITY" : "COMMUNITY"), (community->is_federation) ? "-/-" : community->community); sendto_mgmt(sss, sender_sock, sock_size, (const uint8_t *) resbuf, ressize); ressize = 0; @@ -367,7 +367,7 @@ int process_mgmt (n2n_sn_t *sss, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "%4u | %-19s | %-17s | %-21s %-3s | %-15s | %9s\n", ++num, - (peer->dev_addr.net_addr == 0) ? ((peer->purgeable == UNPURGEABLE) ? "-l" : "") : ip_subnet_to_str(ip_bit_str, &peer->dev_addr), + (peer->dev_addr.net_addr == 0) ? ((peer->purgeable == false) ? "-l" : "") : ip_subnet_to_str(ip_bit_str, &peer->dev_addr), (is_null_mac(peer->mac_addr)) ? "" : macaddr_str(mac_buf, peer->mac_addr), sock_to_cstr(sockbuf, &(peer->sock)), ((peer->socket_fd >= 0) && (peer->socket_fd != sss->sock)) ? "TCP" : "", diff --git a/src/sn_utils.c b/src/sn_utils.c index 16b9d64..8bba52b 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -379,7 +379,7 @@ int load_allowed_sn_community (n2n_sn_t *sss) { if(comm != NULL) { comm_init(comm, cmn_str); /* loaded from file, this community is unpurgeable */ - comm->purgeable = UNPURGEABLE; + comm->purgeable = false; /* we do not know if header encryption is used in this community, * first packet will show. just in case, setup the key. */ comm->header_encryption = HEADER_ENCRYPTION_UNKNOWN; @@ -767,7 +767,7 @@ int sn_init_defaults (n2n_sn_t *sss) { sss->federation->community[N2N_COMMUNITY_SIZE - 1] = '\0'; /* enable the flag for federation */ sss->federation->is_federation = IS_FEDERATION; - sss->federation->purgeable = UNPURGEABLE; + sss->federation->purgeable = false; /* header encryption enabled by default */ sss->federation->header_encryption = HEADER_ENCRYPTION_ENABLED; /*setup the encryption key */ @@ -1075,6 +1075,7 @@ static int update_edge (n2n_sn_t *sss, if(handle_remote_auth(sss, &(reg->auth), answer_auth, comm) == 0) { if(skip_add == SN_ADD) { scan = (struct peer_info *) calloc(1, sizeof(struct peer_info)); /* deallocated in purge_expired_nodes */ + scan->purgeable = true; memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t)); scan->dev_addr.net_addr = reg->dev_addr.net_addr; scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen; @@ -1446,7 +1447,7 @@ static int purge_expired_communities (n2n_sn_t *sss, } } - if((comm->edges == NULL) && (comm->purgeable == PURGEABLE)) { + if((comm->edges == NULL) && (comm->purgeable == true)) { traceEvent(TRACE_INFO, "purging idle community %s", comm->community); if(NULL != comm->header_encryption_ctx_static) { /* this should not happen as 'purgeable' and thus only communities w/o encrypted header here */ @@ -1904,7 +1905,7 @@ static int process_udp (n2n_sn_t * sss, comm->header_encryption_ctx_static = NULL; comm->header_encryption_ctx_dynamic = NULL; /* ... and also are purgeable during periodic purge */ - comm->purgeable = PURGEABLE; + comm->purgeable = true; comm->number_enc_packets = 0; HASH_ADD_STR(sss->communities, community, comm); @@ -2617,7 +2618,7 @@ int run_sn_loop (n2n_sn_t *sss) { #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif - *sss->keep_running = 0; + *sss->keep_running = false; break; } @@ -2735,7 +2736,7 @@ int run_sn_loop (n2n_sn_t *sss) { // REVISIT: should we error out if ss_size returns bigger than before? can this ever happen? if(bread <= 0) { traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", bread, errno, strerror(errno)); - *sss->keep_running = 0; + *sss->keep_running = false; break; } diff --git a/src/supernode.c b/src/supernode.c index b178d81..595c0bd 100644 --- a/src/supernode.c +++ b/src/supernode.c @@ -249,7 +249,7 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { strncpy(anchor_sn->ip_addr, _optarg, N2N_EDGE_SN_HOST_SIZE - 1); memcpy(&(anchor_sn->sock), socket, sizeof(n2n_sock_t)); memcpy(anchor_sn->mac_addr, null_mac, sizeof(n2n_mac_t)); - anchor_sn->purgeable = UNPURGEABLE; + anchor_sn->purgeable = false; anchor_sn->last_valid_time_stamp = initial_time_stamp(); } } @@ -312,7 +312,7 @@ static int setOption (int optkey, char *_optarg, n2n_sn_t *sss) { case 'F': { /* federation name */ snprintf(sss->federation->community, N2N_COMMUNITY_SIZE - 1 ,"*%s", _optarg); sss->federation->community[N2N_COMMUNITY_SIZE - 1] = '\0'; - sss->federation->purgeable = UNPURGEABLE; + sss->federation->purgeable = false; break; } #ifdef SN_MANUAL_MAC @@ -541,7 +541,7 @@ static void dump_registrations (int signo) { /* *************************************************** */ -static int keep_running; +static bool keep_running = true; #if defined(__linux__) || defined(WIN32) #ifdef WIN32 @@ -560,7 +560,7 @@ BOOL WINAPI term_handler (DWORD sig) called = 1; } - keep_running = 0; + keep_running = false; #ifdef WIN32 return(TRUE); #endif @@ -714,7 +714,6 @@ int main (int argc, char * const argv[]) { SetConsoleCtrlHandler(term_handler, TRUE); #endif - keep_running = 1; sss_node.keep_running = &keep_running; return run_sn_loop(&sss_node); } diff --git a/tools/n2n-portfwd.c b/tools/n2n-portfwd.c index b06e6e4..a52fdbf 100644 --- a/tools/n2n-portfwd.c +++ b/tools/n2n-portfwd.c @@ -37,7 +37,7 @@ typedef struct n2n_portfwd_conf { } n2n_portfwd_conf_t; -static int keep_running = 1; /* for main loop, handled by signals */ +static bool keep_running = true; /* for main loop, handled by signals */ // ------------------------------------------------------------------------------------------------------- @@ -73,7 +73,7 @@ static void term_handler (int sig) { called = 1; } - keep_running = 0; + keep_running = false; #ifdef WIN32 return TRUE; #endif diff --git a/tools/n2n-route.c b/tools/n2n-route.c index 4740f9a..9898f5d 100644 --- a/tools/n2n-route.c +++ b/tools/n2n-route.c @@ -69,7 +69,7 @@ typedef struct n2n_route_conf { } n2n_route_conf_t; -static int keep_running = 1; /* for main loop, handled by signals */ +static bool keep_running = true; /* for main loop, handled by signals */ // ------------------------------------------------------------------------------------------------------- @@ -137,7 +137,7 @@ BOOL WINAPI term_handler (DWORD sig) { called = 1; } - keep_running = 0; + keep_running = false; #if defined(WIN32) return TRUE; #endif @@ -827,7 +827,7 @@ int main (int argc, char* argv[]) { if(!inet_address_valid(route->gateway)) { route->gateway = rrr.gateway_vpn; } - route->purgeable = UNPURGEABLE; + route->purgeable = false; handle_route(route, ROUTE_ADD); } @@ -876,7 +876,7 @@ reset_main_loop: rrr.gateway_org = addr_tmp; // delete all purgeable routes as they are still relying on old original default gateway HASH_ITER(hh, rrr.routes, route, tmp_route) { - if((route->purgeable == PURGEABLE)) { + if((route->purgeable == true)) { handle_route(route, ROUTE_DEL); HASH_DEL(rrr.routes, route); free(route); @@ -937,7 +937,7 @@ reset_main_loop: if(now > last_purge + PURGE_INTERVAL) { last_purge = now; HASH_ITER(hh, rrr.routes, route, tmp_route) { - if((route->purgeable == PURGEABLE) && (now > route->last_seen + REMOVE_ROUTE_AGE)) { + if((route->purgeable == true) && (now > route->last_seen + REMOVE_ROUTE_AGE)) { handle_route(route, ROUTE_DEL); HASH_DEL(rrr.routes, route); free(route); @@ -1007,7 +1007,7 @@ reset_main_loop: HASH_DEL(rrr.routes, route); if(route) { fill_route(route, addr, inet_address(HOST_MASK), rrr.gateway_org); - route->purgeable = PURGEABLE; + route->purgeable = true; if(!(route->last_seen)) { handle_route(route, ROUTE_ADD); } From e397a5af753b0bfa5e413bc90ba1bfd804860a6e Mon Sep 17 00:00:00 2001 From: Tony <68118705+Legend-Master@users.noreply.github.com> Date: Sun, 18 Jun 2023 16:02:05 +0800 Subject: [PATCH 2/2] Add close window support for Windows (#1111) * Add close window support for Windows * Support logoff and shudown events as well Without this change, when you close the terminal/shell window, it won't have the time to clean up which can cause authentication errors if you try to reconnect. Blocking here infinitely is fine since when our main thread returns, it will shut down anyway I found Go is doing this when I was searching, and there's a comment explained how it works: https://github.com/golang/go/issues/41884#issuecomment-706695923 --- src/edge.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/edge.c b/src/edge.c index 8bbf162..db4da65 100644 --- a/src/edge.c +++ b/src/edge.c @@ -946,6 +946,13 @@ BOOL WINAPI term_handler(DWORD sig) keep_on_running = false; #ifdef WIN32 + switch (sig) { + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + // Will terminate us after we return, blocking it to cleanup + Sleep(INFINITE); + } return(TRUE); #endif }