mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-09 18:08:31 -10:00
* fix(lockutil): use kernel-held advisory locks * fix(lockutil): harden cross-platform lock files * test(lockutil): require one concurrent holder
40 lines
1.0 KiB
Go
40 lines
1.0 KiB
Go
package oauth
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/Gitlawb/zero/internal/lockutil"
|
|
)
|
|
|
|
const fileLockTimeout = 5 * time.Second
|
|
|
|
// acquireFileLock takes a cross-process advisory lock through a stable lock
|
|
// file. It retries with a short backoff until a timeout. Kernel lock lifetime
|
|
// provides crash recovery, so the path is never renamed or removed.
|
|
func acquireFileLock(lockPath string, now func() time.Time) (func(), error) {
|
|
if now == nil {
|
|
now = time.Now
|
|
}
|
|
if err := os.MkdirAll(filepath.Dir(lockPath), 0o700); err != nil {
|
|
return nil, err
|
|
}
|
|
deadline := now().Add(fileLockTimeout)
|
|
for {
|
|
lock, err := lockutil.TryAcquireFileLock(lockPath)
|
|
if err == nil {
|
|
return func() { _ = lock.Release() }, nil
|
|
}
|
|
if !errors.Is(err, lockutil.ErrLockHeld) {
|
|
return nil, fmt.Errorf("oauth: acquire token lock: %w", err)
|
|
}
|
|
if now().After(deadline) {
|
|
return nil, fmt.Errorf("oauth: timed out acquiring token lock %s", filepath.Base(lockPath))
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
}
|
|
}
|