diff --git a/lib/event-libs/glib/glib.c b/lib/event-libs/glib/glib.c index 386f144f2..b83134b98 100644 --- a/lib/event-libs/glib/glib.c +++ b/lib/event-libs/glib/glib.c @@ -27,7 +27,7 @@ #include #if !defined(G_SOURCE_FUNC) -#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) #endif #define wsi_to_subclass(_w) ((_w)->w_read.glib.source) @@ -35,6 +35,12 @@ #define pt_to_loop(_pt) ((_pt)->glib.loop) #define pt_to_g_main_context(_pt) g_main_loop_get_context(pt_to_loop(_pt)) +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_remove(t.tag); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + static gboolean lws_glib_idle_timer_cb(void *p); @@ -62,17 +68,17 @@ lws_glib_check(GSource *src) static int lws_glib_set_idle(struct lws_context_per_thread *pt) { - GSource *gis; - - if (pt->glib.idle_tag) + if (lws_gs_valid(pt->glib.idle)) return 0; - gis = g_idle_source_new(); - if (!gis) + pt->glib.idle.gs = g_idle_source_new(); + if (!pt->glib.idle.gs) return 1; - g_source_set_callback(gis, lws_glib_idle_timer_cb, pt, NULL); - pt->glib.idle_tag = g_source_attach(gis, pt_to_g_main_context(pt)); + g_source_set_callback(pt->glib.idle.gs, lws_glib_idle_timer_cb, pt, + NULL); + pt->glib.idle.tag = g_source_attach(pt->glib.idle.gs, + pt_to_g_main_context(pt)); return 0; } @@ -80,14 +86,16 @@ lws_glib_set_idle(struct lws_context_per_thread *pt) static int lws_glib_set_timeout(struct lws_context_per_thread *pt, unsigned int ms) { - GSource *gts; + lws_gs_destroy(pt->glib.hrtimer); - gts = g_timeout_source_new(ms); - if (!gts) + pt->glib.hrtimer.gs = g_timeout_source_new(ms); + if (!pt->glib.hrtimer.gs) return 1; - g_source_set_callback(gts, lws_glib_hrtimer_cb, pt, NULL); - pt->glib.hrtimer_tag = g_source_attach(gts, pt_to_g_main_context(pt)); + g_source_set_callback(pt->glib.hrtimer.gs, lws_glib_hrtimer_cb, pt, + NULL); + pt->glib.hrtimer.tag = g_source_attach(pt->glib.hrtimer.gs, + pt_to_g_main_context(pt)); return 0; } @@ -127,7 +135,7 @@ lws_glib_dispatch(GSource *src, GSourceFunc x, gpointer userData) lws_service_fd_tsi(sub->wsi->context, &eventfd, sub->wsi->tsi); - if (!pt->glib.idle_tag) + if (!lws_gs_valid(pt->glib.idle)) lws_glib_set_idle(pt); if (pt->destroy_self) @@ -157,6 +165,9 @@ lws_glib_hrtimer_cb(void *p) lws_usec_t us; lws_pt_lock(pt, __func__); + + lws_gs_destroy(pt->glib.hrtimer); + us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS, lws_now_usecs()); if (us) { @@ -206,7 +217,7 @@ lws_glib_idle_timer_cb(void *p) * We reenable the idle callback on the next network or scheduled event */ - pt->glib.idle_tag = 0; + lws_gs_destroy(pt->glib.idle); return FALSE; } @@ -314,7 +325,7 @@ elops_init_pt_glib(struct lws_context *context, void *_loop, int tsi) if (pt->event_loop_foreign) return 0; - pt->glib.sigint_tag = g_unix_signal_add(SIGINT, + pt->glib.sigint.tag = g_unix_signal_add(SIGINT, G_SOURCE_FUNC(lws_glib_sigint_cb), pt); return 0; @@ -333,6 +344,9 @@ elops_io_glib(struct lws *wsi, int flags) if (!pt_to_loop(pt) || wsi->context->being_destroyed || pt->is_destroyed) return; + if (!wsi_to_subclass(wsi)) + return; + /* * We are being given individual set / clear operations using * LWS_EV_ common namespace, convert them to glib namespace bitfield @@ -357,16 +371,6 @@ elops_io_glib(struct lws *wsi, int flags) lwsl_debug("%s: wsi %p, fd %d, 0x%x/0x%x\n", __func__, wsi, wsi->desc.sockfd, flags, (int)cond); - if (!wsi_to_subclass(wsi)) { - lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); - return; - } - - if (!wsi_to_subclass(wsi)) { - lwsl_err("%s: glib wsi source pointer is NULL\n", __func__); - return; - } - g_source_modify_unix_fd(wsi_to_gsource(wsi), wsi_to_subclass(wsi)->tag, cond); } @@ -402,6 +406,7 @@ elops_destroy_wsi_glib(struct lws *wsi) } g_source_destroy(wsi_to_gsource(wsi)); + g_source_unref(wsi_to_gsource(wsi)); wsi_to_subclass(wsi) = NULL; } @@ -424,12 +429,12 @@ elops_destroy_pt_glib(struct lws_context *context, int tsi) vh = vh->vhost_next; } - if (pt->glib.hrtimer_tag) - g_source_remove(pt->glib.hrtimer_tag); + lws_gs_destroy(pt->glib.idle); + lws_gs_destroy(pt->glib.hrtimer); if (!pt->event_loop_foreign) { g_main_loop_quit(pt_to_loop(pt)); - g_source_remove(pt->glib.sigint_tag); + lws_gs_destroy(pt->glib.sigint); g_main_loop_unref(pt_to_loop(pt)); } diff --git a/lib/event-libs/glib/private-lib-event-libs-glib.h b/lib/event-libs/glib/private-lib-event-libs-glib.h index 00bbf5515..4de461f96 100644 --- a/lib/event-libs/glib/private-lib-event-libs-glib.h +++ b/lib/event-libs/glib/private-lib-event-libs-glib.h @@ -30,11 +30,17 @@ #endif #endif /* LWS_WITH_GLIB */ +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + struct lws_pt_eventlibs_glib { - GMainLoop *loop; - guint hrtimer_tag; - guint sigint_tag; - guint idle_tag; + GMainLoop *loop; + + lws_glib_tag_t hrtimer; + lws_glib_tag_t sigint; + lws_glib_tag_t idle; }; struct lws_io_watcher_glib_subclass { diff --git a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c index 332f08c5b..90049232d 100644 --- a/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c +++ b/minimal-examples/http-server/minimal-http-server-eventlib-foreign/minimal-http-server-eventlib-foreign.c @@ -210,9 +210,19 @@ foreign_event_loop_cleanup_libevent(void) #include #include +typedef struct lws_glib_tag { + GSource *gs; + guint tag; +} lws_glib_tag_t; + +#define lws_gs_valid(t) (t.gs) +#define lws_gs_destroy(t) if (lws_gs_valid(t)) { \ + g_source_remove(t.tag); \ + g_source_unref(t.gs); \ + t.gs = NULL; t.tag = 0; } + static GMainLoop *loop_glib; -static guint timer_outer_glib; -static guint sighandler_glib; +static lws_glib_tag_t timer_outer_glib, sighandler_glib; static int timer_cb_glib(void *p) @@ -234,10 +244,16 @@ foreign_event_loop_init_and_run_glib(void) loop_glib = g_main_loop_new(NULL, 0); - sighandler_glib = g_unix_signal_add(SIGINT, - G_SOURCE_FUNC(signal_cb_glib), NULL); + sighandler_glib.gs = g_unix_signal_source_new(SIGINT); + g_source_set_callback(sighandler_glib.gs, G_SOURCE_FUNC(signal_cb_glib), + NULL, NULL); + sighandler_glib.tag = g_source_attach(sighandler_glib.gs, + g_main_loop_get_context(loop_glib)); - timer_outer_glib = g_timeout_add(1000, timer_cb_glib, NULL); + timer_outer_glib.gs = g_timeout_source_new(1000); + g_source_set_callback(timer_outer_glib.gs, timer_cb_glib, NULL, NULL); + timer_outer_glib.tag = g_source_attach(timer_outer_glib.gs, + g_main_loop_get_context(loop_glib)); g_main_loop_run(loop_glib); } @@ -252,8 +268,12 @@ static void foreign_event_loop_cleanup_glib(void) { /* cleanup the foreign loop assets */ - g_source_remove(sighandler_glib); + + lws_gs_destroy(sighandler_glib); + lws_gs_destroy(timer_outer_glib); + g_main_loop_unref(loop_glib); + loop_glib = NULL; } #endif