chenBright commented on code in PR #3535:
URL: https://github.com/apache/brpc/pull/3535#discussion_r4455646517


##########
src/brpc/ubshm/ub_ring.cpp:
##########
@@ -220,41 +221,9 @@ RETURN_CODE UBRing::UbrAddHBTimer() {
     return UBRING_OK;
 }
 
-RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx *trx, int fd, PASSIVE_DISC_TYPE 
type) {
-    RETURN_CODE passive_close_check_rc = UbrTrxCloseCheck(trx);
-    if (UNLIKELY(passive_close_check_rc != UBRING_OK)) {
-        if (passive_close_check_rc == UBRING_REENTRY) {
-            LOG(INFO) << "Passive close skipped, active close in progress, 
name=" << trx->local_shm.name;
-            uint64_t start_time = GetCurNanoSeconds();
-            return ClearTrxResource(trx, start_time, UBR_CALL_BACK_CLOSE);
-        }
-        return UBRING_ERR;
-    }
-    trx->ubr_tx.trx_state = UBR_STATE_CLOSED;
-    trx->ubr_rx.trx_state = UBR_STATE_CLOSED;
-    DeleteTimerSafe((uint32_t)trx->timer_fd);
-    const char *type_name = nullptr;
-    if (type == UBR_HEARTBEAT) {
-        DeleteTimer((uint32_t)trx->hb_timer_fd);
-        type_name = "Trx heartbeat";
-    } else if (type == UBR_UB_EVENT) {
-        DeleteTimerSafe((uint32_t)trx->hb_timer_fd);
-        type_name = "Ub event callback";
-    }
-    constexpr int64_t kMicrosecondsPerSecond = 1000000LL;
-    bthread_usleep(FLAGS_ub_flying_io_timeout_s * kMicrosecondsPerSecond);
-
-    int rc = ShmLocalFree(&trx->remote_shm);
-    if (rc != UBRING_OK) {
-        LOG(ERROR) << type_name << ", delete remote shm failed. ret=" << rc;
-    }
-    rc = ShmLocalFree(&trx->local_shm);
-    if (rc != UBRING_OK) {
-        LOG(ERROR) << type_name << ", delete local shm failed. ret=" << rc;
-    }
-
-    UBRingManager::ReleaseUbrTrxFromMgr(trx);
-    return UBRING_OK;
+RETURN_CODE UBRing::UbrPassiveClearTrx(UbrTrx* trx) {
+    const RETURN_CODE rc = ClearTrxResource(trx, UBR_PASSIVE_CLOSE);
+    return rc == UBRING_REENTRY ? UBRING_OK : rc;

Review Comment:
   After passive disconnection was changed to use `ClearTrxResource()`, it 
eventually calls `UbrTrxFreeShm()`. That function returns immediately if the 
local `ShmMunmap()` fails, so the remote `ShmLocalFree()` is not executed. For 
example, when the UBS backend returns `UBSM_ERR_NET`, only the local SHM enters 
the retry queue, while the asynchronous callback still releases the cleanup 
reference. Afterward, because the state is already `UBR_CLOSE_SECOND`, 
`UbrTrxClose()` only releases the ring reference and does not perform the 
missed remote cleanup. Even if the local retry succeeds, cleanup of the remote 
mapping is still missed. The original passive path attempted to free both sides 
independently; please preserve that behavior and arrange retries for each 
failed resource.



##########
src/brpc/ubshm/ub_ring.cpp:
##########
@@ -61,7 +61,44 @@ RETURN_CODE UBRing::UbrTrxMapShm(SHM *local_shm, SHM 
*remote_shm)
     return UBRING_OK;
 }
 
+RETURN_CODE UBRing::UbrTrxAbort() {
+    if (_trx == nullptr) {
+        return UBRING_OK;
+    }
+    if (ATOMIC_LOAD(_trx->close_state) != UBR_CLOSE_FIRST) {
+        return ReleaseTrx();
+    }
+    const RETURN_CODE close_rc = UbrTrxCloseCheck(_trx);
+    if (close_rc != UBRING_OK) {
+        return close_rc;
+    }
+    int expected = UBR_CLOSE_FIRST;
+    if (!ATOMIC_COMPARE_EXCHANGE_STRONG(
+            _trx->close_state, expected, UBR_CLOSE_SECOND)) {
+        return ReleaseTrx();
+    }
+    // Drain timer callbacks before unmapping the queues they access.
+    DeleteTimerSafe(_trx->timer_fd);
+    DeleteTimerSafe(_trx->hb_timer_fd);
+    DeleteTimerSafe(_trx->clear_timer_fd);
+    RETURN_CODE rc = UbrTrxFreeShm(_trx);
+    if (rc == UBRING_OK) {
+        rc = ReleaseTrx();
+    }

Review Comment:
   When using `SHM_TYPE_UBS` during an upgrade rollback, the `UBSM_ERR_NET` 
branch in `ShmMunmap()` adds the SHM to the retry queue and causes 
`UbrTrxFreeShm()` to return an error, so `ReleaseTrx()` is skipped here. 
However, the caller, `UBShmEndpoint::Reset()`, still deletes the ring 
afterward, and the transaction timer has already been canceled; the SHM retry 
callback does not release the transaction reference. A single failure will 
permanently occupy a transaction slot. As failures accumulate, UBSHM 
transactions can no longer be allocated, and `UbrMgrFini()` will continue 
waiting. Please explicitly transfer responsibility for retrying failed 
resources and ensure that the transaction reference held by the ring is 
eventually released.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to