| Age | Commit message (Collapse) | Author | Lines |
|
|
|
A failed truncate or key write returned with the descriptor still open,
so the lock was held while the page rendered uncached and the file was
left behind. It is removed before its last close, as every holder does.
|
|
process_slot logged every failure to lock, so each request that found
its slot being filled left a line, while refresh_slot logged none, so an
expired slot in a directory the server cannot write was served stale for
good without a word. lock_slot now logs the step that failed, as the
scan does, and leaves out only another request at work.
|
|
Each exec filter and snapshot compressor a fill runs inherited the slot's
lock descriptor beside the stdout it writes into. An flock lasts until
its last copy closes and nothing waits for a process a filter leaves
behind, so a fill killed before its rename could leave the slot locked,
and served stale or uncached, for as long as such a process lived.
The scan holds its lock across no exec and opens the same way so that
the two stay alike.
|
|
|
|
|
|
|
|
|
|
The cache root always holds a default or a copy, the key comes from a
strbuf, and every string hashed is the same or a macro expansion.
|
|
|
|
The slot lock was a POSIX record lock, which a process loses the moment
any descriptor on the file closes, and the fill puts the lock file on
stdout, which every exec filter and snapshot compressor closes with its
dup2. A second request on the slot could then rebuild it under the first
and splice the two pages. An flock holds until the last descriptor goes.
|
|
The slot being filled was forgotten before the page's final flush, so a
write that failed there, on a full disk for one, could not abandon the
fill: cgit died into the lock file instead and the visitor got nothing.
The mid-page path already delivered the page from the lock file.
|
|
A ttl in the tens of millions of minutes overflowed the int it was
multiplied in.
|
|
xread and xwrite may move fewer bytes than asked. A short write of the
key left a slot that could never match, a short read of it reported a
collision, and a page write that moved nothing looped for ever.
|
|
sendfile returns zero at the end of the file, and the loop only ended
once the offset reached the size recorded when the slot was opened, so
a slot cut shorter in between spun the request forever. Only Linux
builds this path. A stand-in header type checked it here.
|
|
A write that failed with EPIPE on an uncached page died into an error
page, which died again at exit when the page could not be sent either,
and git logged a recursion warning on every dropped connection. A
filter that exits early fails a write the same way, so the quiet exit
is kept for writes that reach the client itself.
|
|
The dumb transport reads files that already sit on the disk, so a pack
copied into a slot cost that disk twice and the request a second write
of every byte. A snapshot took a slot whatever its size, so a visitor
naming distinct refs and ids could fill the cache root with archives.
`cache-max-slot-size`, 64 MB unless set, now serves a larger response
from the lock file and drops it, along with any expired copy it would
have replaced.
|
|
|
|
|
|
|
|
A filter program that could not be run answered with two responses,
and a filter that exited without reading its input ended cgit with
the page half written.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AUTHORS now records the upstream developers as the project's history
rather than as maintainers of the fork.
|
|
The C sources move to source/, the served files to assets/, the bundled
Git submodule to libraries/git and the filter scripts to extensions/.
Everything the build generates now lands in build/, so a clean is a
single remove and the tree stays clean.
|