From 6f8e255f45fb2cde26d126d96974e2c9a94603eb Mon Sep 17 00:00:00 2001 From: Sherlock0203 <1297399478@qq.com> Date: Tue, 1 Sep 2026 11:03:17 +0800 Subject: [PATCH 1/2] =?UTF-8?q?[fix]=E6=B3=A8=E9=87=8A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/brpc/ubshm/timer/timer_mgr.cpp | 4 ++-- src/brpc/ubshm/timer/timer_mgr.h | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/brpc/ubshm/timer/timer_mgr.cpp b/src/brpc/ubshm/timer/timer_mgr.cpp index c803716a94..3d114b4a4c 100644 --- a/src/brpc/ubshm/timer/timer_mgr.cpp +++ b/src/brpc/ubshm/timer/timer_mgr.cpp @@ -236,8 +236,8 @@ int UbrTimerDel(UbrTimerId* slot) { } // ==1: dispatched, OnFire (owned==false) // releases it ReleaseRef(task); // owner - return 0; // the callback is guaranteed never to run: the caller - // consumes the timer/callback reference + return 0; // suppressed: for a one-shot the callback never runs, and + // the caller consumes the timer/callback reference } void UbrTimerDelAndWait(UbrTimerId* slot) { diff --git a/src/brpc/ubshm/timer/timer_mgr.h b/src/brpc/ubshm/timer/timer_mgr.h index 74e5083ce7..2b5fdd428a 100644 --- a/src/brpc/ubshm/timer/timer_mgr.h +++ b/src/brpc/ubshm/timer/timer_mgr.h @@ -47,14 +47,20 @@ RETURN_CODE UbrTimerStart(UbrTimerId* slot, uint64_t delay_us, // Non-blocking delete, safe from inside the timer callback itself. Does // not wait for a running callback and does not protect `arg' on its own. -// Returns 0 when the call won the slot competition: a one-shot callback -// is guaranteed never to run, and the caller consumes any per-task -// resources it tracks for this timer (ownership of them transfers to the -// caller); for a periodic timer an already-started callback is not -// interrupted. Returns 1 when the callback has been dispatched (it -// consumes those resources itself on every exit) or its fate is still -// being settled by the scheduler -- the caller must not consume anything -// then. +// Suppression is arbitrated by the handle-slot competition (see OnFire): +// this call returns 0 when it won that competition. For a one-shot timer +// the callback is then guaranteed never to run -- OnFire observes the +// lost slot race and skips -- even when bthread_timer_del reports the +// timer as already dispatched; ownership of caller-tracked per-task +// resources transfers to the caller. For a periodic timer winning the +// competition only removes the timer from the dispatch queue: an already +// dispatched or started callback may still run (at most once more), so +// the caller must not reclaim resources reachable from `arg' on this +// return alone; use UbrTimerDelAndWait for that. +// Returns 1 when the callback side owns the resources: the callback has +// run or will run and consumes them on every exit, or the timer was never +// armed and the scheduling path settles them. The caller must not consume +// anything on 1. int UbrTimerDel(UbrTimerId* slot); // Delete and wait until a possibly running callback finished, so the From c98758becc5540cc033b448dd8f211095dcdf644 Mon Sep 17 00:00:00 2001 From: Sherlock0203 <1297399478@qq.com> Date: Tue, 1 Sep 2026 11:48:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?[fix]=E6=B3=A8=E9=87=8A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/brpc/ubshm/timer/timer_mgr.cpp | 6 ++++-- src/brpc/ubshm/timer/timer_mgr.h | 30 ++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/brpc/ubshm/timer/timer_mgr.cpp b/src/brpc/ubshm/timer/timer_mgr.cpp index 3d114b4a4c..d4d4e6d5de 100644 --- a/src/brpc/ubshm/timer/timer_mgr.cpp +++ b/src/brpc/ubshm/timer/timer_mgr.cpp @@ -236,8 +236,10 @@ int UbrTimerDel(UbrTimerId* slot) { } // ==1: dispatched, OnFire (owned==false) // releases it ReleaseRef(task); // owner - return 0; // suppressed: for a one-shot the callback never runs, and - // the caller consumes the timer/callback reference + return 0; // This call won the slot competition. For a one-shot timer, + // the callback will not run. For a periodic timer, future + // rearming is stopped, but an already dispatched or running + // callback may still complete. } void UbrTimerDelAndWait(UbrTimerId* slot) { diff --git a/src/brpc/ubshm/timer/timer_mgr.h b/src/brpc/ubshm/timer/timer_mgr.h index 2b5fdd428a..f4d244eceb 100644 --- a/src/brpc/ubshm/timer/timer_mgr.h +++ b/src/brpc/ubshm/timer/timer_mgr.h @@ -45,22 +45,20 @@ RETURN_CODE UbrTimerStart(UbrTimerId* slot, uint64_t delay_us, void* arg, UbrTimerBackoffFn backoff = nullptr); -// Non-blocking delete, safe from inside the timer callback itself. Does -// not wait for a running callback and does not protect `arg' on its own. -// Suppression is arbitrated by the handle-slot competition (see OnFire): -// this call returns 0 when it won that competition. For a one-shot timer -// the callback is then guaranteed never to run -- OnFire observes the -// lost slot race and skips -- even when bthread_timer_del reports the -// timer as already dispatched; ownership of caller-tracked per-task -// resources transfers to the caller. For a periodic timer winning the -// competition only removes the timer from the dispatch queue: an already -// dispatched or started callback may still run (at most once more), so -// the caller must not reclaim resources reachable from `arg' on this -// return alone; use UbrTimerDelAndWait for that. -// Returns 1 when the callback side owns the resources: the callback has -// run or will run and consumes them on every exit, or the timer was never -// armed and the scheduling path settles them. The caller must not consume -// anything on 1. +// Non-blocking delete, safe to call from inside the timer callback itself. +// This function does not wait for an already running callback and does not +// protect resources reachable from `arg` on its own. +// +// Returns 0 when this call wins the handle-slot competition. +// - For a one-shot timer, the callback will not run. +// - For a periodic timer, future rearming is stopped, but an already +// dispatched or running callback may still execute once more. Callers +// must not reclaim resources reachable from `arg` based on this return +// alone; use UbrTimerDelAndWait when teardown needs to wait for callbacks. +// +// Returns 1 when this caller did not acquire timer ownership. The callback, +// another deleter, or the scheduling path is responsible for settling the +// timer resources, so this caller must not reclaim them. int UbrTimerDel(UbrTimerId* slot); // Delete and wait until a possibly running callback finished, so the