#include #include #include #include #include #include #include #include #include #include static struct osmo_fd g_evfd; static void *alloc_res_select; static void *alloc_res_global; static int destructor_called; static int talloc_destructor(void *ptr) { printf("destructor was called automatically\n"); /* ensure the destructor is only called for the chunk allocated from the * volatile select context */ OSMO_ASSERT(ptr == alloc_res_select); destructor_called += 1; return 0; } static int evfd_cb(struct osmo_fd *ofd, unsigned int what) { uint64_t rval; int rc; rc = read(ofd->fd, &rval, sizeof(rval)); OSMO_ASSERT(rc == sizeof(rval)); printf("allocating from select context\n"); alloc_res_select = talloc_named_const(OTC_SELECT, 23, "alloc_select"); OSMO_ASSERT(alloc_res_select); talloc_set_destructor(alloc_res_select, talloc_destructor); printf("allocating from global context\n"); alloc_res_global = talloc_named_const(OTC_GLOBAL, 42, "alloc_global"); OSMO_ASSERT(alloc_res_global); talloc_set_destructor(alloc_res_global, talloc_destructor); return 0; } const struct log_info_cat default_categories[] = { }; static struct log_info info = { .cat = default_categories, .num_cat = ARRAY_SIZE(default_categories), }; int main(int argc, char **argv) { int rc; osmo_init_logging2(OTC_GLOBAL, &info); rc = eventfd(0, 0); OSMO_ASSERT(rc >= 0); osmo_fd_setup(&g_evfd, rc, OSMO_FD_READ, evfd_cb, NULL, 0); osmo_fd_register(&g_evfd); /* make sure the select loop will immediately call the callback */ uint64_t val = 1; rc = write(g_evfd.fd, &val, sizeof(val)); OSMO_ASSERT(rc == sizeof(val)); /* enter osmo_select_main_ctx() once */ printf("entering osmo_select_main\n"); osmo_select_main_ctx(1); /* the allocation must have happened, and the destructor must have been called * automatically exactly once */ OSMO_ASSERT(destructor_called == 1); exit(0); }