flock-contract.md 3.2 KB

POSIX flock behavior

tryLockExclusive(fd) returns a promise for one flock(fd, LOCK_EX | LOCK_NB) attempt. The syscall runs off the JavaScript thread. The caller keeps the descriptor open through completion; the binding does not open, duplicate, or close it. It exposes neither a blocking-wait API nor a shared-lock API.

Behavior tests

The native tests exercise real descriptors and independent processes. The C oracle calls the operating system directly, independently of system.node.

Condition Required observation
No conflicting lock Acquisition resolves to void
Same open file description acquires again Acquisition succeeds without a second ownership record
Separate opens of the same file Exactly one exclusive holder; the contender rejects with EAGAIN/EWOULDBLOCK
Different files Both can be locked
Independent C flock holder The addon cannot acquire, and the C oracle cannot acquire while the addon holds the lock
A shared flock holder The addon's exclusive attempt conflicts
Holder remains live A nonblocking attempt reports contention before the holder unlocks
Ordinary read/write by another process Access is allowed: flock is advisory, not an I/O permission mechanism
One unrelated descriptor closes The actual holder keeps its lock
A descriptor inherited by a child remains open Closing the parent's descriptor does not release the shared open file description's lock
Last owning descriptor closes An already-open contender can acquire
Holder process exits or is killed Acquisition succeeds after process exit, without a stale-lock timeout
Invalid descriptor The promise rejects with EBADF and positive errno
Native argument validation fails The JavaScript entry returns a rejected promise without throwing synchronously
Native completion callback It receives zero or the request's positive errno asynchronously
Native completion callback throws The exception reaches Node's uncaught-exception handler
Concurrent success/failure calls Each completion receives its own syscall errno
Worker environment terminates before or during its callback Native work and cleanup reach completion without taking ownership of the caller's descriptor

Tests synchronize through IPC or flushed line protocols and await process exit before asserting crash recovery. They do not use fixed sleeps or a millisecond performance threshold to prove nonblocking behavior. The syscall oracle is built only for tests and never included in a published platform package.

Limits

Locks belong to open file descriptions and follow the host filesystem's flock semantics. Removing or replacing a pathname does not transfer a lock to the replacement inode; the JSONL backend separately checks inode identity. Network filesystems can have different or unsupported lock semantics. Windows does not use this API and retains its existing semaphore implementation.

Node-API compatibility tests reuse the same platform addon under different Node versions. They complement these syscall tests; loading a binary alone does not prove correct locking behavior.