|atomic-invoke doesn't reset ar-sema-cell if its thunk throws an error:|
After an error has been thrown from the thunk in one non-nested call to atomic, further calls to atomic execute its thunk immediately without being guarded by the semaphore.
arc> (errsafe (atomic (/ 1 0)))
> (thread-cell-ref ar-sema-cell)
One fix is to use dynamic-wind:
...though full continuation jumps are blocked across call-with-semaphore, so dynamic-wind might be heavier than you need.
(if (thread-cell-ref ar-sema-cell)
(ar-apply f '())
(lambda () (thread-cell-set! ar-sema-cell #t))
(lambda () (ar-apply f '()))))
(lambda () (thread-cell-set! ar-sema-cell #f))))))