1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

glib: stop leaking idle and hrtimer source

This gives a valgrind result for lws-minimal-http-server-event-lib-foreign
that's clean for lws pieces, although glib is always dirty wrt thread local
storage and hashtable.
This commit is contained in:
Andy Green 2020-06-30 21:08:05 +01:00
parent b72ab32c17
commit dfed547529
3 changed files with 70 additions and 39 deletions

View file

@ -27,7 +27,7 @@
#include <glib-unix.h>
#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));
}

View file

@ -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 {

View file

@ -210,9 +210,19 @@ foreign_event_loop_cleanup_libevent(void)
#include <glib-2.0/glib.h>
#include <glib-unix.h>
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