we can't use Sync with stl mutex types since yielding from one coroutine
to another while holding a lock is a deadlock hazard. if we don't expose
blocking lock operations from Sync though and emulate blocking with more
promises we can reuse most of the Sync code instead of rewriting it all.
hiding them completely would make it impossible to migrate current users
to promise-based code though, so we use our new NeverAsync lint instead.
Change-Id: I7eebf18e29473963040e7448da27c52012f1f134
gc tryLocks first, then deletes. we can use the same order since there's
no sequence of operations that would let us lock our new directory *and*
have the gc delete it (except outright bugs). the worst possible outcome
is that we create a few directories that'll be deleted by a later gc run
Change-Id: I6d3524f4990f8deee10804e6fbb0d0a26f3d57fe
we now create a temporary file, lock it, move it into place, and return.
if any of these steps (except creation) fails the GC must have found and
deleted our new file before we got the chance to use it. we don't need a
lock around file creation anymore, we especially don't need a mutex that
covers an flock call, and we don't need the GC to clobber what it finds.
(clobbering *is* kept for compatibility with older nix implementations.)
if we ever leave trash around it'll be cleaned up by some future gc run.
Change-Id: I078ae55fb7a9dfcdae28d6917d138842188ed528
sadly we need both a synchronous and an asynchronous promise for this
since destructors cannot be async. we also cannot use forked promises
since multiple threads may be waiting for an auto-gc to complete, but
forked promises are bound to an event loop (and thus a single thread)
Change-Id: I7b4fdbd229c4a1e01bbf80858e93347024f2e333
constructors can't be async, and root creation must be made async.
creating roots outside of goal classes and passing a witness type
is a lot easier than changing the constructor structure of today.
Change-Id: Ic84a92f3db2e1a9a9164047456f227048c6871bd
addMultipleToStore calls addToStore through processGraph, so for now we
need an aio root in processGraph callbacks. eventually we'll drop them,
but that can only be done once we know that the single-threaded runtime
will not get deadlocked. the threads guarantee progress, for time being
Change-Id: I62869a72ef8085c508609a8d4274330e004ab685
the other completers already inherit one through EvalState. all of them
eventually need it since completing a flake ref may require network io.
Change-Id: Ie664a129a68457a6f0908d226057d7d7fb610ae4
the LocalStore implementation calls `getDefaultSubstituters`, which
calls `openStore`, which calls `Store::init`, which does network io
in binary caches, which will eventually be properly asyncified curl
Change-Id: If6a7a0294e2c4ba8e35722583be6ccde21ed6585
we now allow for single locked paths rather than only sets, the lock
holder classes are finally resource-safe, and not locking files from
within constructors means we can (in theory!) make path locks async.
Change-Id: I1e1807299d370c07b15c332d5b2ff77b64456e7d
they are not being created with O_EXCL and their existence is not
checked for using the PathLocks api, so we will boldy assume that
*nothing* checks for lock file existence. deleting lockfiles when
we're done with them in all cases makes the code cleaner, and any
failing builds no longer litter their store with stale lockfiles.
Change-Id: Iffb588d29b00e6aca32fcb6776980455238ac2bd
the local store doesn't have to block the entire thread waiting for a
lock with such support. we'll still block *some* thread, but there is
currently no good way around that without e.g. a lock manager daemon.
Change-Id: I037fdc749e1b56cf9e0f1ca7ac70274442fb2b8c