| Age | Commit message (Collapse) | Author | Lines |
|
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.
|
|
lock_slot() opens the lock file with O_RDWR|O_CREAT but without
O_TRUNC. If a previous cgit process was killed between lock_slot() and
unlock_slot() (e.g. by a CGI timeout or OOM), the stale lock file
remains on disk with the old content, and the kernel releases the fcntl
lock.
The next process to claim the same cache slot then opens this stale lock
file, acquires the fcntl lock, writes its key and generated content on
top of the old bytes. If the new response is shorter than what was
previously in the file, trailing bytes from the old response survive
beyond the end of the new content. fstat() in fill_slot() reports the
total file size (including the stale tail), and print_slot() faithfully
sends all of it -- producing a response that is the correct page
followed by a fragment of whatever previously occupied that lock file.
Fix this by truncating the lock file after acquiring the lock and before
writing the new key.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
sendfile() can return after a short read/write, so we may need to call
it more than once. As suggested in the manual page, we fall back to
read/write if sendfile fails with EINVAL or ENOSYS.
On the read/write path, use write_in_full which deals with short writes.
Signed-off-by: Hristo Venev <hristo@venev.name>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
Update to git version v2.30.0, this requires changes for these
upstream commits:
* 88894aaeeae92e8cb41143cc2e045f50289dc790
blame: simplify 'setup_scoreboard' interface
* 1fbfdf556f2abc708183caca53ae4e2881b46ae2
banned.h: mark non-reentrant gmtime, etc as banned
Signed-off-by: Christian Hesse <mail@eworm.de>
|
|
We use POSIX advisory record locks to control access to cache slots, but
these have an unhelpful behaviour in that they are released when any
file descriptor referencing the file is closed by this process.
Mostly this is okay, since we know we won't be opening the lock file
anywhere else, but there is one place that it does matter: when we
restore stdout we dup2() over a file descriptor referring to the file,
thus closing that descriptor.
Since we restore stdout before unlocking the slot, this creates a window
during which the slot content can be overwritten. The fix is reasonably
straightforward: simply restore stdout after unlocking the slot, but the
diff is a bit bigger because this requires us to move the temporary
stdout FD into struct cache_slot.
Signed-off-by: John Keeping <john@keeping.me.uk>
Reviewed-by: Christian Hesse <mail@eworm.de>
|
|
Signed-off-by: Ville Skyttä <ville.skytta@iki.fi>
|
|
As described in commit 2efb59e (ui-patch: Flush stdout after outputting
data, 2014-06-11), we need to ensure that stdout is flushed before
restoring the file descriptor when writing to the cache. It turns out
that it's not just ui-patch that is affected by this but also raw diff
which writes to stdout internally.
Let's avoid risking more places doing this by ensuring that stdout is
flushed after writing in fill_slot().
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
We call open_slot() from cache_ls() without a key since we simply want
to read the path out of the header. Should the file happen to contain
an empty key then we end up calling memcmp() with NULL and a non-zero
length. Fix this by assigning slot->match only if a key is set, which
is always will be in the code paths where we use slot->match.
Coverity-id: 13807
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Avoid integer truncation on 64-bit systems.
Coverity-id: 13864
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Coverity-id: 13910
Signed-off-by: Christian Hesse <mail@eworm.de>
|
|
git-compat-util.h may define values that affect how system headers are
interpreted, so move sys/sendfile.h after cgit.h (which includes
git-compat-util.h).
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
If CGit is killed while it holds a lock on a cache slot (for example
because it is taking too long to generate a page), the lock file will be
left in place. This prevents any future attempt to use the same slot
since it will fail to exclusively create the lock file.
Since CGit is the only program that should be manipulating lock files,
we can use advisory locking to detect whether another process is
actually using the lock file or if it is now stale.
I have confirmed that this works on Linux by setting a short TTL in a
custom cgitrc and running the following with CGit patched to print a
message to stderr if the fcntl(2) fails:
$ export CGIT_CONFIG=$PWD/cgitrc
$ export QUERY_STRING=url=cgit/tree/ui-shared.c
$ ./cgit |
grep -v -e '^<div class=.footer.>' \
-e '^Last-Modified: ' \
-e ^'Expires: ' >expect
$ seq 50000 | dd bs=8192 |
parallel -j200 "diff -u expect <(./cgit |
grep -v -e '^<div class=.footer.>' \
-e '^Last-Modified: ' \
-e ^'Expires: ') || echo BAD"
This printed the fail message several times without ever printing "BAD".
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
If time-to-live is set to zero, we don't need to regenerate the cache
slots on every request. Instead, just skip the caching process and
immediately provide the dynamically generated version of the page.
Setting time-to-live to zero is useful when you want to disable caching
for certain pages.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
|
|
sendfile() does the same job and avoids to copy the content into userland
and back. One has to define NO_SENDFILE in case the OS (kernel / libc)
does not supported. It is disabled by default on non-linux environemnts.
According to the glibc, sendfile64() was added in Linux 2.4 (so it has
been there for a while) but after browsing over the mapage of FreeBSD's I
noticed that the prototype is little different.
Signed-off-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc>
|
|
Drop the context parameter from the following functions (and all static
helpers used by them) and use the global context instead:
* cgit_print_http_headers()
* cgit_print_docstart()
* cgit_print_pageheader()
Remove context parameter from all commands
Drop the context parameter from the following functions (and all static
helpers used by them) and use the global context instead:
* cgit_get_cmd()
* All cgit command functions.
* cgit_clone_info()
* cgit_clone_objects()
* cgit_clone_head()
* cgit_print_plain()
* cgit_show_stats()
In initialization routines, use the global context variable instead of
passing a pointer around locally.
Remove callback data parameter for cache slots
This is no longer needed since the context is always read from the
global context variable.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
|
|
Valgrind says:
==18344== Conditional jump or move depends on uninitialised value(s)
==18344== at 0x406C83: open_slot (cache.c:63)
==18344== by 0x407478: cache_ls (cache.c:403)
==18344== by 0x404C9A: process_request (cgit.c:639)
==18344== by 0x406BD2: fill_slot (cache.c:190)
==18344== by 0x4071A0: cache_process (cache.c:284)
==18344== by 0x404461: main (cgit.c:952)
==18344== Uninitialised value was created by a stack allocation
==18344== at 0x40738B: cache_ls (cache.c:375)
This is caused by the keylen field being used to calculate whether or
not a slot is matched. We never then check the value of this and the
length of data read depends on the key length read from the file so this
isn't dangerous, but it's nice to avoid branching based on uninitialized
data.
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
* Name "cgit Development Team" as copyright holder to avoid listing
every single developer.
* Update copyright ranges.
Signed-off-by: Lukas Fleischer <cgit@crytocrack.de>
|
|
By using the standard library's printf, cache_ls does not redirect its
output to the cache when we change the process' stdout file descriptor
to point to the cache file. Fix this by using "htmlf" in the same way
that we do for writing HTTP headers.
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Commit fb3655d (use struct strbuf instead of static buffers, 2013-04-06)
broke the logic in cache.c::cache_ls by failing to set slot->cache_name
before calling open_slot.
While fixing this, also free the strbufs added by that commit once we're
done with them.
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Use "struct strbuf" from Git to remove the limit on file path length.
Notes on scan-tree:
This is slightly involved since I decided to pass the strbuf into
add_repo() and modify if whenever a new file name is required, which
should avoid any extra allocations within that function. The pattern
there is to append the filename, use it and then reset the buffer to its
original length (retaining a trailing '/').
Notes on ui-snapshot:
Since write_archive modifies the argv array passed to it we
copy the argv_array values into a new array of char* and then free the
original argv_array structure and the new array without worrying about
what the values now look like.
Signed-off-by: John Keeping <john@keeping.me.uk>
|
|
Spotted by parsing the output of `gcc -Wmissing-prototypes [...]`.
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
|
|
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
* Remove whitespace at the end of lines.
* Replace space indentation by tabs.
* Add whitespace before/after several operators ("+", "-", "*", ...)
* Add whitespace to assignments ("foo = bar;").
* Fix whitespace in parameter lists ("foobar(foo, bar, 42)").
Signed-off-by: Lukas Fleischer <cgit@cryptocrack.de>
|
|
The type used to declare the st_size field of a 'struct stat' can
be a 32- or 64-bit sized type, which can vary from one platform to
another, or even from one compilation to another. In particular,
on linux, if you include the following define:
#define _FILE_OFFSET_BITS 64
prior to including certain system header files, then the type used
for the st_size field will be __off64_t, otherwise it will be an
__off_t. Note that the above define is included at the top of
git-compat-util.h.
In cache.c, the "%zd" format specifier expects a "signed size_t",
another type which can vary, when an __off64_t or a __off_t is
provided. To supress the warning, use the PRIuMAX format specifier
and cast the st_size field to uintmax_t. This should work an any
platform for which git currently compiles.
In ui-plain.c, the size parameter of sha1_object_info() and
read_sha1_file() is defined to be "unsigned long *" not "size_t *".
So, to supress the warning, simply declare size with the correct type.
Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
Signed-off-by: Lars Hjemli <hjemli@gmail>
|
|
The change to print_slot() in cdc6b2f8e7a8d43dcfe0475a9d3498333ea686b8 made
the function return correct errno for read errors while ignoring write errors,
which is not what was intended. This patch tries to rectify things.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
If print_slot() fails, the client will be served an inferior response.
This patch makes sure that such an error will be returned to main(), which
in turn will try to inform about the error in the response itself.
The error is also printed to the cache_log, i.e. stderr, which will make
the error message appear in error_log (atleast when httpd==apache).
Noticed-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
These functions handles EINTR/EAGAIN errors during read/write operations,
which is something cache.c didn't.
While at it, fix a bug in print_slot() where errors during reading from the
cache slot might go by unnoticed.
Noticed-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
We'll need proper return-values from these functions to make the cache
behave correctly (which includes giving proper error messages).
Noticed-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
Noticed-by: Jim Meyering <jim@meyering.net>
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|
|
This new page will list all entries found in the current cache, which is
useful when reviewing the new cache implementation. There are no links to
the new page, but it's reachable by adding 'p=ls_cache' to any cgit url.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
|