Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package libdex for openSUSE:Factory checked in at 2025-07-02 18:17:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libdex (Old) and /work/SRC/openSUSE:Factory/.libdex.new.7067 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libdex" Wed Jul 2 18:17:14 2025 rev:11 rq:1289801 version:0.10.1 Changes: -------- --- /work/SRC/openSUSE:Factory/libdex/libdex.changes 2025-05-30 17:22:20.539809351 +0200 +++ /work/SRC/openSUSE:Factory/.libdex.new.7067/libdex.changes 2025-07-02 18:17:41.555871085 +0200 @@ -1,0 +2,13 @@ +Sat Jun 28 07:28:45 UTC 2025 - Bjørn Lie <bjorn....@gmail.com> + +- Update to version 0.10.1: + + Fix autoptr usage + + Raise critical on finalization of thread-pool-scheduler which + should not happen in proper usage of libdex + + Avoid extra pointer chase when dispatching to thread pool + workers + + Don't dispatch blocks while on fibers, wait for scheduler + + Fix leak of unix signal futures + + Improve management of fiber run queues + +------------------------------------------------------------------- Old: ---- libdex-0.10.0.obscpio New: ---- libdex-0.10.1.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libdex.spec ++++++ --- /var/tmp/diff_new_pack.WcxQp6/_old 2025-07-02 18:17:42.227899007 +0200 +++ /var/tmp/diff_new_pack.WcxQp6/_new 2025-07-02 18:17:42.227899007 +0200 @@ -20,7 +20,7 @@ %bcond_with profiling Name: libdex -Version: 0.10.0 +Version: 0.10.1 Release: 0 Summary: Library supporting "Deferred Execution" for GNOME and GTK License: LGPL-2.1-or-later ++++++ _service ++++++ --- /var/tmp/diff_new_pack.WcxQp6/_old 2025-07-02 18:17:42.255900170 +0200 +++ /var/tmp/diff_new_pack.WcxQp6/_new 2025-07-02 18:17:42.259900337 +0200 @@ -3,7 +3,7 @@ <service name="obs_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://gitlab.gnome.org/GNOME/libdex.git</param> - <param name="revision">0.10.0</param> + <param name="revision">0.10.1</param> <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> <param name="versionrewrite-pattern">v?(.*)\+0</param> <param name="versionrewrite-replacement">\1</param> ++++++ libdex-0.10.0.obscpio -> libdex-0.10.1.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/NEWS new/libdex-0.10.1/NEWS --- old/libdex-0.10.0/NEWS 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/NEWS 2025-06-28 00:19:53.000000000 +0200 @@ -1,3 +1,14 @@ +libdex 0.10.1 +============= + + * Fix autoptr usage + * Raise critical on finalization of thread-pool-scheduler which should + not happen in proper usage of libdex + * Avoid extra pointer chase when dispatching to thread pool workers + * Don't dispatch blocks while on fibers, wait for scheduler + * Fix leak of unix signal futures + * Improve management of fiber run queues + libdex 0.10.0 ============= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/meson.build new/libdex-0.10.1/meson.build --- old/libdex-0.10.0/meson.build 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/meson.build 2025-06-28 00:19:53.000000000 +0200 @@ -1,5 +1,5 @@ project('libdex', 'c', - version: '0.10.0', + version: '0.10.1', meson_version: '>= 1.0.0', default_options: [ 'warning_level=2', 'werror=false', 'c_std=gnu11', ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-block.c new/libdex-0.10.1/src/dex-block.c --- old/libdex-0.10.0/src/dex-block.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-block.c 2025-06-28 00:19:53.000000000 +0200 @@ -188,7 +188,8 @@ /* If we are on the same scheduler that created this block, then * we can execute it now. */ - if (block->scheduler == dex_scheduler_get_thread_default () && + if (storage->fiber_scheduler == NULL && + block->scheduler == dex_scheduler_get_thread_default () && storage->sync_dispatch_depth < DEX_DISPATCH_RECURSE_MAX) { gboolean ret; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-cancellable.c new/libdex-0.10.1/src/dex-cancellable.c --- old/libdex-0.10.0/src/dex-cancellable.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-cancellable.c 2025-06-28 00:19:53.000000000 +0200 @@ -87,7 +87,7 @@ dex_cancellable_cancelled_cb (GCancellable *cancellable, DexWeakRef *wr) { - g_autoptr(DexCancellable) self = NULL; + DexCancellable *self; g_assert (G_IS_CANCELLABLE (cancellable)); g_assert (wr != NULL); @@ -100,6 +100,7 @@ g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "Operation cancelled")); + dex_clear (&self); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-channel.c new/libdex-0.10.1/src/dex-channel.c --- old/libdex-0.10.0/src/dex-channel.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-channel.c 2025-06-28 00:19:53.000000000 +0200 @@ -442,8 +442,9 @@ DexFuture * dex_channel_receive_all (DexChannel *channel) { - g_autoptr(GPtrArray) ret = NULL; + GPtrArray *ret = NULL; GQueue stolen = G_QUEUE_INIT; + DexFuture *future = NULL; g_return_val_if_fail (DEX_IS_CHANNEL (channel), NULL); @@ -470,15 +471,22 @@ while (stolen.length > 0) dex_channel_item_free (g_queue_pop_head_link (&stolen)->data); - return dex_future_allv ((DexFuture **)ret->pdata, ret->len); + future = dex_future_allv ((DexFuture **)ret->pdata, ret->len); + goto cleanup; reject_receive: dex_object_unlock (channel); - return dex_future_new_for_error (g_error_copy (&channel_closed_error)); + future = dex_future_new_for_error (g_error_copy (&channel_closed_error)); + goto cleanup; wait_for_result: dex_object_unlock (channel); - return dex_future_all (dex_channel_receive (channel), NULL); + future = dex_future_all (dex_channel_receive (channel), NULL); + goto cleanup; + +cleanup: + g_clear_pointer (&ret, g_ptr_array_unref); + return future; } static void diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-delayed.c new/libdex-0.10.1/src/dex-delayed.c --- old/libdex-0.10.0/src/dex-delayed.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-delayed.c 2025-06-28 00:19:53.000000000 +0200 @@ -114,6 +114,12 @@ { } +/** + * dex_delayed_new: + * @future: (transfer none): a [class@Dex.Future] + * + * Returns: (transfer full): + */ DexFuture * dex_delayed_new (DexFuture *future) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-fiber-private.h new/libdex-0.10.1/src/dex-fiber-private.h --- old/libdex-0.10.0/src/dex-fiber-private.h 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-fiber-private.h 2025-06-28 00:19:53.000000000 +0200 @@ -40,6 +40,13 @@ typedef struct _DexFiberScheduler DexFiberScheduler; +enum { + QUEUE_NONE, + QUEUE_RUNNABLE, + QUEUE_BLOCKED, + LAST_QUEUE +}; + struct _DexFiber { DexFuture parent_instance; @@ -55,6 +62,7 @@ guint exited : 1; guint released : 1; guint cancelled : 1; + guint queue : 2; /* The requested stack size */ gsize stack_size; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-fiber.c new/libdex-0.10.1/src/dex-fiber.c --- old/libdex-0.10.0/src/dex-fiber.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-fiber.c 2025-06-28 00:19:53.000000000 +0200 @@ -66,6 +66,31 @@ static DexFuture *cancelled_future; static void +dex_fiber_scheduler_set_queue (DexFiberScheduler *scheduler, + DexFiber *fiber, + guint queue) +{ + g_assert (scheduler != NULL); + g_assert (fiber != NULL); + g_assert (queue < LAST_QUEUE); + + if (fiber->queue == queue) + return; + + if (fiber->queue == QUEUE_RUNNABLE) + g_queue_unlink (&scheduler->runnable, &fiber->link); + else if (fiber->queue == QUEUE_BLOCKED) + g_queue_unlink (&scheduler->blocked, &fiber->link); + + fiber->queue = queue; + + if (queue == QUEUE_RUNNABLE) + g_queue_push_tail_link (&scheduler->runnable, &fiber->link); + else if (queue == QUEUE_BLOCKED) + g_queue_push_tail_link (&scheduler->blocked, &fiber->link); +} + +static void dex_fiber_discard (DexFuture *future) { DexFiber *fiber = DEX_FIBER (future); @@ -82,8 +107,7 @@ if (!fiber->runnable) { - g_queue_unlink (&fiber->fiber_scheduler->blocked, &fiber->link); - g_queue_push_tail_link (&fiber->fiber_scheduler->runnable, &fiber->link); + dex_fiber_scheduler_set_queue (fiber->fiber_scheduler, fiber, QUEUE_RUNNABLE); if (dex_thread_storage_get ()->fiber_scheduler != fiber->fiber_scheduler) source = g_source_ref ((GSource *)fiber->fiber_scheduler); @@ -128,8 +152,7 @@ fiber->runnable = TRUE; - g_queue_unlink (&fiber->fiber_scheduler->blocked, &fiber->link); - g_queue_push_tail_link (&fiber->fiber_scheduler->runnable, &fiber->link); + dex_fiber_scheduler_set_queue (fiber->fiber_scheduler, fiber, QUEUE_RUNNABLE); if (dex_thread_storage_get ()->fiber_scheduler != fiber->fiber_scheduler) source = g_source_ref ((GSource *)fiber->fiber_scheduler); @@ -151,6 +174,7 @@ { DexFiber *fiber = DEX_FIBER (object); + g_assert (fiber->queue == QUEUE_NONE); g_assert (fiber->fiber_scheduler == NULL); g_assert (fiber->link.data == fiber); g_assert (fiber->link.prev == NULL); @@ -297,7 +321,12 @@ gboolean ret; g_mutex_lock (&fiber_scheduler->mutex); - ret = fiber_scheduler->runnable.length != 0; + + g_assert (fiber_scheduler->runnable.length == 0 || fiber_scheduler->runnable.head != NULL); + g_assert (fiber_scheduler->runnable.length > 0 || fiber_scheduler->runnable.head == NULL); + + ret = fiber_scheduler->runnable.head != NULL; + g_mutex_unlock (&fiber_scheduler->mutex); return ret; @@ -307,14 +336,20 @@ dex_fiber_scheduler_prepare (GSource *source, int *timeout) { + gboolean ret; + *timeout = -1; - return dex_fiber_scheduler_check (source); + + ret = dex_fiber_scheduler_check (source); + + return ret; } static gboolean dex_fiber_scheduler_iteration (DexFiberScheduler *fiber_scheduler) { DexFiber *fiber; + gboolean ret; g_assert (fiber_scheduler != NULL); @@ -324,12 +359,14 @@ dex_ref (fiber); g_assert (fiber->fiber_scheduler == fiber_scheduler); + g_assert (fiber->link.data == fiber); fiber->running = TRUE; fiber_scheduler->running = fiber; dex_fiber_ensure_stack (fiber, fiber_scheduler); } + g_mutex_unlock (&fiber_scheduler->mutex); if (fiber == NULL) @@ -342,7 +379,7 @@ fiber_scheduler->running = NULL; if (!fiber->released && fiber->exited) { - g_queue_unlink (&fiber_scheduler->runnable, &fiber->link); + dex_fiber_scheduler_set_queue (fiber->fiber_scheduler, fiber, QUEUE_NONE); if (fiber->stack->size == fiber_scheduler->stack_pool->stack_size) dex_stack_pool_release (fiber_scheduler->stack_pool, @@ -355,11 +392,12 @@ dex_unref (fiber); } + ret = fiber_scheduler->runnable.length > 0; g_mutex_unlock (&fiber_scheduler->mutex); dex_unref (fiber); - return TRUE; + return ret; } static gboolean @@ -453,7 +491,8 @@ fiber->fiber_scheduler = fiber_scheduler; fiber->runnable = TRUE; - g_queue_push_tail_link (&fiber_scheduler->runnable, &fiber->link); + + dex_fiber_scheduler_set_queue (fiber_scheduler, fiber, QUEUE_RUNNABLE); g_mutex_unlock (&fiber_scheduler->mutex); @@ -481,8 +520,7 @@ g_mutex_lock (&fiber_scheduler->mutex); fiber->runnable = FALSE; cancelled = fiber->cancelled; - g_queue_unlink (&fiber_scheduler->runnable, &fiber->link); - g_queue_push_tail_link (&fiber_scheduler->blocked, &fiber->link); + dex_fiber_scheduler_set_queue (fiber_scheduler, fiber, QUEUE_BLOCKED); g_mutex_unlock (&fiber_scheduler->mutex); /* Now request the future notify us of completion */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-thread-pool-scheduler.c new/libdex-0.10.1/src/dex-thread-pool-scheduler.c --- old/libdex-0.10.0/src/dex-thread-pool-scheduler.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-thread-pool-scheduler.c 2025-06-28 00:19:53.000000000 +0200 @@ -27,6 +27,8 @@ #include "dex-thread-storage-private.h" #include "dex-work-queue-private.h" +#define MAX_WORKERS 32 + /** * DexThreadPoolScheduler: * @@ -52,8 +54,9 @@ DexScheduler parent_instance; DexWorkQueue *global_work_queue; DexThreadPoolWorkerSet *set; - GPtrArray *workers; guint fiber_rrobin; + guint n_workers; + DexThreadPoolWorker *workers[MAX_WORKERS]; }; typedef struct _DexThreadPoolSchedulerClass @@ -66,6 +69,8 @@ #undef DEX_TYPE_THREAD_POOL_SCHEDULER #define DEX_TYPE_THREAD_POOL_SCHEDULER dex_thread_pool_scheduler_type +static DexScheduler *default_thread_pool; + static void dex_thread_pool_scheduler_push (DexScheduler *scheduler, DexWorkItem work_item) @@ -110,8 +115,8 @@ DexFiber *fiber) { DexThreadPoolScheduler *thread_pool_scheduler = (DexThreadPoolScheduler *)scheduler; - guint worker_index = g_atomic_int_add (&thread_pool_scheduler->fiber_rrobin, 1) % thread_pool_scheduler->workers->len; - DexThreadPoolWorker *worker = thread_pool_scheduler->workers->pdata[worker_index]; + guint worker_index = g_atomic_int_add (&thread_pool_scheduler->fiber_rrobin, 1) % thread_pool_scheduler->n_workers; + DexThreadPoolWorker *worker = thread_pool_scheduler->workers[worker_index]; /* TODO: This is just doing a dumb round robin for assigning a fiber to a * specific thread pool worker. We probably want something more interesting @@ -127,10 +132,19 @@ { DexThreadPoolScheduler *thread_pool_scheduler = (DexThreadPoolScheduler *)object; + if ((DexScheduler *)thread_pool_scheduler == default_thread_pool) + { + g_critical ("Attempt to finalize default thread pool. " + "This should not happen and is an error in the application."); + return; + } + dex_clear (&thread_pool_scheduler->global_work_queue); g_clear_pointer (&thread_pool_scheduler->set, dex_thread_pool_worker_set_unref); - g_clear_pointer (&thread_pool_scheduler->workers, g_ptr_array_unref); + + for (guint i = 0; i < thread_pool_scheduler->n_workers; i++) + dex_clear (&thread_pool_scheduler->workers[i]); DEX_OBJECT_CLASS (dex_thread_pool_scheduler_parent_class)->finalize (object); } @@ -154,7 +168,6 @@ { thread_pool_scheduler->global_work_queue = dex_work_queue_new (); thread_pool_scheduler->set = dex_thread_pool_worker_set_new (); - thread_pool_scheduler->workers = g_ptr_array_new_with_free_func (dex_unref); } /** @@ -175,7 +188,7 @@ /* TODO: let this be dynamic and tunable, as well as thread pinning */ - n_procs = MIN (32, g_get_num_processors ()); + n_procs = MIN (MAX_WORKERS, g_get_num_processors ()); /* Couple things here, which we should take a look at in the future to * see how we can tune them correctly, but: @@ -199,10 +212,10 @@ thread_pool_worker = dex_thread_pool_worker_new (thread_pool_scheduler->global_work_queue, thread_pool_scheduler->set); - if (thread_pool_worker != NULL) - g_ptr_array_add (thread_pool_scheduler->workers, g_steal_pointer (&thread_pool_worker)); - else + if (thread_pool_worker == NULL) break; + + thread_pool_scheduler->workers[thread_pool_scheduler->n_workers++] = thread_pool_worker; } return DEX_SCHEDULER (thread_pool_scheduler); @@ -222,8 +235,6 @@ DexScheduler * dex_thread_pool_scheduler_get_default (void) { - static DexScheduler *default_thread_pool; - if (g_once_init_enter (&default_thread_pool)) { DexScheduler *instance = dex_thread_pool_scheduler_new (); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/src/dex-unix-signal.c new/libdex-0.10.1/src/dex-unix-signal.c --- old/libdex-0.10.0/src/dex-unix-signal.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/src/dex-unix-signal.c 2025-06-28 00:19:53.000000000 +0200 @@ -95,6 +95,8 @@ g_value_init (&value, G_TYPE_INT); g_value_set_int (&value, unix_signal->signum); dex_future_complete (DEX_FUTURE (unix_signal), &value, NULL); + + dex_unref (unix_signal); } return G_SOURCE_REMOVE; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/testsuite/test-future.c new/libdex-0.10.1/testsuite/test-future.c --- old/libdex-0.10.0/testsuite/test-future.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/testsuite/test-future.c 2025-06-28 00:19:53.000000000 +0200 @@ -408,6 +408,7 @@ g_assert_error (error, DEX_ERROR, DEX_ERROR_DEPENDENCY_FAILED); \ g_assert_null (value); \ g_main_loop_quit (main_loop); \ + g_error_free (error); \ return NULL; \ } \ static void \ @@ -871,7 +872,7 @@ test_delayed_simple (void) { DexFuture *result = dex_future_new_for_int (123); - DexFuture *delayed = dex_delayed_new (dex_ref (result)); + DexFuture *delayed = dex_delayed_new (result); ASSERT_STATUS (result, DEX_FUTURE_STATUS_RESOLVED); ASSERT_STATUS (delayed, DEX_FUTURE_STATUS_PENDING); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/testsuite/test-semaphore.c new/libdex-0.10.1/testsuite/test-semaphore.c --- old/libdex-0.10.0/testsuite/test-semaphore.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/testsuite/test-semaphore.c 2025-06-28 00:19:53.000000000 +0200 @@ -124,6 +124,8 @@ g_test_message ("Thread %d handled %d items", i, state[i].handled); } + + dex_unref (semaphore); } int diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libdex-0.10.0/testsuite/test-stream.c new/libdex-0.10.1/testsuite/test-stream.c --- old/libdex-0.10.0/testsuite/test-stream.c 2025-03-15 20:01:29.000000000 +0100 +++ new/libdex-0.10.1/testsuite/test-stream.c 2025-06-28 00:19:53.000000000 +0200 @@ -59,6 +59,9 @@ g_main_loop_run (main_loop); + g_object_unref (stream); + g_object_unref (file); + value = dex_future_get_value (future, &error); g_assert_no_error (error); g_assert_nonnull (value); ++++++ libdex.obsinfo ++++++ --- /var/tmp/diff_new_pack.WcxQp6/_old 2025-07-02 18:17:42.415906818 +0200 +++ /var/tmp/diff_new_pack.WcxQp6/_new 2025-07-02 18:17:42.419906984 +0200 @@ -1,5 +1,5 @@ name: libdex -version: 0.10.0 -mtime: 1742065289 -commit: 094958a3780b5ab4652c0547774a1b24862ac25d +version: 0.10.1 +mtime: 1751062793 +commit: ac2ac4508a3e4b2be821ee2fb559fc3697d57cfc