<p>laforge <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/13312">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">context: Add support for [per-thread] global talloc contexts<br><br>Rather than having applications maintain their own talloc cotexts,<br>let's offer some root talloc contexts in libosmocore.  Let's also<br>make them per thread right from the beginning.  This will help<br>some multi-threaded applications to use talloc in a thread-safe<br>way.<br><br>Change-Id: Iae39cd57274bf6753ecaf186f229e582b42662e3<br>---<br>M include/osmocom/core/select.h<br>M include/osmocom/core/talloc.h<br>M src/Makefile.am<br>A src/context.c<br>M src/select.c<br>M tests/Makefile.am<br>A tests/context/context_test.c<br>A tests/context/context_test.ok<br>M tests/testsuite.at<br>9 files changed, 213 insertions(+), 9 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/select.h b/include/osmocom/core/select.h</span><br><span>index e4787b0..a200b6f 100644</span><br><span>--- a/include/osmocom/core/select.h</span><br><span>+++ b/include/osmocom/core/select.h</span><br><span>@@ -51,6 +51,7 @@</span><br><span> void osmo_fd_unregister(struct osmo_fd *fd);</span><br><span> void osmo_fd_close(struct osmo_fd *fd);</span><br><span> int osmo_select_main(int polling);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_select_main_ctx(int polling);</span><br><span> </span><br><span> struct osmo_fd *osmo_fd_get_by_fd(int fd);</span><br><span> </span><br><span>diff --git a/include/osmocom/core/talloc.h b/include/osmocom/core/talloc.h</span><br><span>index 191a463..c68a56c 100644</span><br><span>--- a/include/osmocom/core/talloc.h</span><br><span>+++ b/include/osmocom/core/talloc.h</span><br><span>@@ -1,5 +1,27 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \file talloc.h</span><br><span style="color: hsl(0, 100%, 40%);">- * Convenience wrapper.  libosmocore used to ship its own internal copy of</span><br><span style="color: hsl(0, 100%, 40%);">- * talloc, before libtalloc became a standard component on most systems */</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file talloc.h */</span><br><span> #pragma once</span><br><span> #include <talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! per-thread talloc contexts.  This works around the problem that talloc is not</span><br><span style="color: hsl(120, 100%, 40%);">+ * thread-safe. However, one can simply have a different set of talloc contexts for each</span><br><span style="color: hsl(120, 100%, 40%);">+ * thread, and ensure that allocations made on one thread are always only free'd on that</span><br><span style="color: hsl(120, 100%, 40%);">+ * very same thread.</span><br><span style="color: hsl(120, 100%, 40%);">+ * WARNING: Users must make sure they free() on the same thread as they allocate!! */</span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_talloc_contexts {</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! global per-thread talloc context. */</span><br><span style="color: hsl(120, 100%, 40%);">+      void *global;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! volatile select-dispatch context.  This context is completely free'd and</span><br><span style="color: hsl(120, 100%, 40%);">+       * re-created every time the main select loop in osmo_select_main() returns from</span><br><span style="color: hsl(120, 100%, 40%);">+       * select(2) and calls per-fd callback functions.  This allows users of this</span><br><span style="color: hsl(120, 100%, 40%);">+   * facility to allocate temporary objects like string buffers, message buffers</span><br><span style="color: hsl(120, 100%, 40%);">+         * and the like which are automatically free'd when going into the next select()</span><br><span style="color: hsl(120, 100%, 40%);">+   * system call */</span><br><span style="color: hsl(120, 100%, 40%);">+     void *select;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+extern __thread struct osmo_talloc_contexts *osmo_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* short-hand #defines for the osmo talloc contexts (OTC) that can be used to pass</span><br><span style="color: hsl(120, 100%, 40%);">+ * to the various _c functions like msgb_alloc_c() */</span><br><span style="color: hsl(120, 100%, 40%);">+#define OTC_GLOBAL (osmo_ctx->global)</span><br><span style="color: hsl(120, 100%, 40%);">+#define OTC_SELECT (osmo_ctx->select)</span><br><span>diff --git a/src/Makefile.am b/src/Makefile.am</span><br><span>index f937810..245eb6d 100644</span><br><span>--- a/src/Makefile.am</span><br><span>+++ b/src/Makefile.am</span><br><span>@@ -13,7 +13,7 @@</span><br><span> lib_LTLIBRARIES = libosmocore.la</span><br><span> </span><br><span> libosmocore_la_LIBADD = $(BACKTRACE_LIB) $(TALLOC_LIBS) $(LIBRARY_RT)</span><br><span style="color: hsl(0, 100%, 40%);">-libosmocore_la_SOURCES = timer.c timer_gettimeofday.c timer_clockgettime.c \</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore_la_SOURCES = context.c timer.c timer_gettimeofday.c timer_clockgettime.c \</span><br><span>                        select.c signal.c msgb.c bits.c \</span><br><span>                    bitvec.c bitcomp.c counter.c fsm.c \</span><br><span>                         write_queue.c utils.c socket.c \</span><br><span>diff --git a/src/context.c b/src/context.c</span><br><span>new file mode 100644</span><br><span>index 0000000..bad012b</span><br><span>--- /dev/null</span><br><span>+++ b/src/context.c</span><br><span>@@ -0,0 +1,52 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \file context.c</span><br><span style="color: hsl(120, 100%, 40%);">+ * talloc context handling.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2019 by Harald Welte <laforge@gnumonks.org></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserverd.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * SPDX-License-Identifier: GPL-2.0+</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ *  it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ *  the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ *  (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ *  GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ *  along with this program; if not, write to the Free Software</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,</span><br><span style="color: hsl(120, 100%, 40%);">+ *  MA  02110-1301, USA.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+__thread struct osmo_talloc_contexts *osmo_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_ctx_init(const char *id)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_ctx = talloc_named(NULL, sizeof(*osmo_ctx), "global-%s", id);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!osmo_ctx)</span><br><span style="color: hsl(120, 100%, 40%);">+                return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+       memset(osmo_ctx, 0, sizeof(*osmo_ctx));</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_ctx->global = osmo_ctx;</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_ctx->select = talloc_named_const(osmo_ctx->global, 0, "select");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!osmo_ctx->select) {</span><br><span style="color: hsl(120, 100%, 40%);">+           talloc_free(osmo_ctx);</span><br><span style="color: hsl(120, 100%, 40%);">+                return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* initialize osmo_ctx on main tread */</span><br><span style="color: hsl(120, 100%, 40%);">+static __attribute__((constructor)) void on_dso_load_ctx(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(osmo_ctx_init("main") == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! @} */</span><br><span>diff --git a/src/select.c b/src/select.c</span><br><span>index 7ce135f..394a59d 100644</span><br><span>--- a/src/select.c</span><br><span>+++ b/src/select.c</span><br><span>@@ -36,6 +36,8 @@</span><br><span> #include <osmocom/core/linuxlist.h></span><br><span> #include <osmocom/core/timer.h></span><br><span> #include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span> </span><br><span> #include "../config.h"</span><br><span> </span><br><span>@@ -233,11 +235,7 @@</span><br><span>       return work;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! select main loop integration</span><br><span style="color: hsl(0, 100%, 40%);">- *  \param[in] polling should we pollonly (1) or block on select (0)</span><br><span style="color: hsl(0, 100%, 40%);">- *  \returns 0 if no fd handled; 1 if fd handled; negative in case of error</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-int osmo_select_main(int polling)</span><br><span style="color: hsl(120, 100%, 40%);">+static int _osmo_select_main(int polling)</span><br><span> {</span><br><span>     fd_set readset, writeset, exceptset;</span><br><span>         int rc;</span><br><span>@@ -259,10 +257,42 @@</span><br><span>      /* fire timers */</span><br><span>    osmo_timers_update();</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_ctx->select);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* call registered callback functions */</span><br><span>     return osmo_fd_disp_fds(&readset, &writeset, &exceptset);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! select main loop integration</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] polling should we pollonly (1) or block on select (0)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 if no fd handled; 1 if fd handled; negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_select_main(int polling)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc = _osmo_select_main(polling);</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef EMBEDDED</span><br><span style="color: hsl(120, 100%, 40%);">+        if (talloc_total_size(osmo_ctx->select) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_panic("You cannot use the 'select' volatile "</span><br><span style="color: hsl(120, 100%, 40%);">+                     "context if you don't use osmo_select_main_ctx()!\n");</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+     return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#ifndef EMBEDDED</span><br><span style="color: hsl(120, 100%, 40%);">+/*! select main loop integration with temporary select-dispatch talloc context</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] polling should we pollonly (1) or block on select (0)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 if no fd handled; 1 if fd handled; negative in case of error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_select_main_ctx(int polling)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc = _osmo_select_main(polling);</span><br><span style="color: hsl(120, 100%, 40%);">+  /* free all the children of the volatile 'select' scope context */</span><br><span style="color: hsl(120, 100%, 40%);">+    talloc_free_children(osmo_ctx->select);</span><br><span style="color: hsl(120, 100%, 40%);">+    return rc;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! find an osmo_fd based on the integer fd</span><br><span>  *  \param[in] fd file descriptor to use as search key</span><br><span>  *  \returns \ref osmo_fd for \ref fd; NULL in case it doesn't exist */</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index a8a06c5..92edf75 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -32,6 +32,7 @@</span><br><span>                  tdef/tdef_vty_test_dynamic                             \</span><br><span>             sockaddr_str/sockaddr_str_test                         \</span><br><span>             use_count/use_count_test                               \</span><br><span style="color: hsl(120, 100%, 40%);">+              context/context_test                                   \</span><br><span>             $(NULL)</span><br><span> </span><br><span> if ENABLE_MSGFILE</span><br><span>@@ -251,6 +252,9 @@</span><br><span> use_count_use_count_test_SOURCES = use_count/use_count_test.c</span><br><span> use_count_use_count_test_LDADD = $(LDADD)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+context_context_test_SOURCES = context/context_test.c</span><br><span style="color: hsl(120, 100%, 40%);">+context_context_test_LDADD = $(LDADD)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # The `:;' works around a Bash 3.2 bug when the output is not writeable.</span><br><span> $(srcdir)/package.m4: $(top_srcdir)/configure.ac</span><br><span>        :;{ \</span><br><span>@@ -322,6 +326,7 @@</span><br><span>       tdef/tdef_vty_test_dynamic.vty \</span><br><span>             sockaddr_str/sockaddr_str_test.ok \</span><br><span>          use_count/use_count_test.ok use_count/use_count_test.err \</span><br><span style="color: hsl(120, 100%, 40%);">+            context/context_test.ok \</span><br><span>            $(NULL)</span><br><span> </span><br><span> DISTCLEANFILES = atconfig atlocal conv/gsm0503_test_vectors.c</span><br><span>diff --git a/tests/context/context_test.c b/tests/context/context_test.c</span><br><span>new file mode 100644</span><br><span>index 0000000..e9a5559</span><br><span>--- /dev/null</span><br><span>+++ b/tests/context/context_test.c</span><br><span>@@ -0,0 +1,84 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdlib.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <unistd.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdio.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <sys/eventfd.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/logging.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/application.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/utils.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/select.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/talloc.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fd g_evfd;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void *alloc_res_select;</span><br><span style="color: hsl(120, 100%, 40%);">+static void *alloc_res_global;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int destructor_called;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int talloc_destructor(void *ptr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("destructor was called automatically\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    /* ensure the destructor is only called for the chunk allocated from the</span><br><span style="color: hsl(120, 100%, 40%);">+       * volatile select context */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(ptr == alloc_res_select);</span><br><span style="color: hsl(120, 100%, 40%);">+ destructor_called += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int evfd_cb(struct osmo_fd *ofd, unsigned int what)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint64_t rval;</span><br><span style="color: hsl(120, 100%, 40%);">+        int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = read(ofd->fd, &rval, sizeof(rval));</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(rc == sizeof(rval));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("allocating from select context\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ alloc_res_select = talloc_named_const(OTC_SELECT, 23, "alloc_select");</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(alloc_res_select);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_set_destructor(alloc_res_select, talloc_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("allocating from global context\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ alloc_res_global = talloc_named_const(OTC_GLOBAL, 42, "alloc_global");</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(alloc_res_global);</span><br><span style="color: hsl(120, 100%, 40%);">+        talloc_set_destructor(alloc_res_global, talloc_destructor);</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const struct log_info_cat default_categories[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct log_info info = {</span><br><span style="color: hsl(120, 100%, 40%);">+     .cat = default_categories,</span><br><span style="color: hsl(120, 100%, 40%);">+    .num_cat = ARRAY_SIZE(default_categories),</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int main(int argc, char **argv)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_init_logging2(OTC_GLOBAL, &info);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  rc = eventfd(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(rc >= 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fd_setup(&g_evfd, rc, OSMO_FD_READ, evfd_cb, NULL, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_fd_register(&g_evfd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* make sure the select loop will immediately call the callback */</span><br><span style="color: hsl(120, 100%, 40%);">+    uint64_t val = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     rc = write(g_evfd.fd, &val, sizeof(val));</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(rc == sizeof(val));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* enter osmo_select_main_ctx() once */</span><br><span style="color: hsl(120, 100%, 40%);">+       printf("entering osmo_select_main\n");</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_select_main_ctx(1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* the allocation must have happened, and the destructor must have been called</span><br><span style="color: hsl(120, 100%, 40%);">+         * automatically exactly once */</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(destructor_called == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        exit(0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/tests/context/context_test.ok b/tests/context/context_test.ok</span><br><span>new file mode 100644</span><br><span>index 0000000..3984a39</span><br><span>--- /dev/null</span><br><span>+++ b/tests/context/context_test.ok</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+entering osmo_select_main</span><br><span style="color: hsl(120, 100%, 40%);">+allocating from select context</span><br><span style="color: hsl(120, 100%, 40%);">+allocating from global context</span><br><span style="color: hsl(120, 100%, 40%);">+destructor was called automatically</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index 0fc9646..a043f0c 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -350,3 +350,9 @@</span><br><span> cat $abs_srcdir/use_count/use_count_test.err > experr</span><br><span> AT_CHECK([$abs_top_builddir/tests/use_count/use_count_test], [0], [expout], [experr])</span><br><span> AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([context])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([context])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/context/context_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/context/context_test], [0], [expout], [ignore])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/13312">change 13312</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/13312"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Iae39cd57274bf6753ecaf186f229e582b42662e3 </div>
<div style="display:none"> Gerrit-Change-Number: 13312 </div>
<div style="display:none"> Gerrit-PatchSet: 19 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: Max <suraev@alumni.ntnu.no> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>