It's now easier to cross compile a 2.5 kb hello world program for win32,
on arm64 xnu, that'll run on the very latest Windows, e.g.
cosmo-make -j12 m=x86_64 o/x86_64/tool/hello/hello-pe.ape
This is essentially a rewrite of the entire `fexecve` implementation. We
no longer attempt to attempt to assimilate APEs in mem -- if the syscall
fails we fallback to sys_execve(/dev/fd/X so the APE loader can be used.
When a zipos file descriptor is passed, the new memfd is now only leaked
if the file has zipos (is a ZIP file) or is an APE, otherwise FD_CLOEXEC
is set on it (so non-zip ELFs do not leak). Previously FD_CLOEXEC on APE
binaries was not set when copying to a `memfd`, due to the security risk
of still leaking a fd, we no longer do so. FD_CLOEXEC does not work with
the APE loader (we may be able to later add support using AT_EXECFD). On
Linux, non-zip ELF files with only execute permissions may be opened and
run with _OPATH. The new version is vforksafe+asyncsignalsafe. To ensure
even on failure, the `memfd` will be cleaned up, pthread_cleanup_push is
used. zipos fexecve fails with `ENOTSUP` when `__vforked` so it does not
leak a `memfd` into the parent process if there is pthread cancellation.
The tests were revamped to more completely cover the various branches of
ELF or APE, zip file or not, `FD_CLOEXEC`, `O_PATH`, zipos fd or not, or
vforked. Additionally, there are checks for fd leaks. Feature testing is
done on Linux for the tests that rely on kernels newer than 2.6.18 so in
theory they should still pass on old Linux. For now, the zipos (f)execve
tests are only enabled on Linux as they have not been tested on FreeBSD.
The test files pass on Linux, Qemu user aarch64/x86_64, and Windows Ten.
Third party libraries in superconfigure have compiler checks, that error
out for C23, so the preference would be to use C17 for a while until all
those libraries are updated.
- Open flags (e.g. O_CREAT) are now constants
- Error numbers (e.g. EINVAL) are now constants
- Signal numbers (e.g. SIGINT) are now constants
- fcntl() file locks now work properly on Windows
- Significantly improve Windows path handling code
- Implement true vfork() on Windows and make fork() faster
- Implement scanf %[charset] support and improve conformance
- Introduce $COSMOSDRIVE so you can use Windows 11 dev drives
- Fix stdio seek/tell bug and make stdio locks faster and safer
- Change TLS ABI to use tlscc wrapper that inserts function calls
- Make malloc() faster on all platforms using new cosmo_shard() api
- Make malloc() fast like tcmalloc on Linux using restartable sequences
- Improve fsync() and fdatasync() polyfills so they abstract robustness
- Fix CLOCK_BOOTTIME and CLOCK_MONOTONIC on XNU so it reflects uptime
- Fix bugs in Windows overlapped code that could possibly cause crash
- Fix bugs in Windows signal code that could possibly cause crash
- Make symlinks with multiple components work right on Windows
- Add FreeBSD ELF note to remove SIGBUS issue and other quirks
- Support symlinks on Windows under non-administrator accounts
- Make kisdangerous() scalable by adding radix trie to mmap()
- Make large realloc() operations zero-cost on all platforms
- Fix bugs in readdir() on Windows where d_reclen wasn't set
- Make all system call wrappers memory safe (raises EFAULT)
- Fix bugs in poll() and select() on Windows with 64+ fds
- Fix bug in madvise() on Windows that could cause crash
- Support WUNTRACED, SIGSTOP, and SIGCONT on Windows
- Increase x86 image base from 0x400000 to 0x4200000
- Introduce -msysv and -mtinylinux flags to cosmocc
- Fix issues with siglongjmp() on XNU and NetBSD
- Make pthread_barrier_wait() work correctly
- Make clock_gettime() faster on FreeBSD ARM
- Support file mode bits better on Windows
- Improve performance of string libraries
- Raise EILSEQ when creating evil paths
- Fix std::terminate to not use malloc
- Modernize more c11 and c23 features
- Make pthread_once() exception safe
- Support RLIMIT_CPU on Windows
- Introduce HACL* cryptography
- Introduce cosmopolitan make
- Introduce fasterzip program
- Introduce open_memstream()
- Introduce dedupe program
- Introduce arc4random()
- Introduce f2fs support
When redbean is starting up, if you don't explicitly specify a port then
it'll choose the default one, which is 8080. If that port is in use then
redbean will increment the port number up to 20 times before it gives up
This change fixes a segmentation fault when comparing loaders that don't
have a target kernel set. Additionally, adds evbarm, which is the output
of uname -m on NetBSD on aarch64.
Let's say you pass the `-M blink-mips.elf` flag to apelink, so that your
ape binary will bundle a compressed build of blink, and the shell script
will extract that binary and launch your program under it, if running on
a MIPS system. However, for any given microprocessor architecture, we'll
need a separate loader for each operating system. The issue is ELF OSABI
isn't very useful. As an example, SerenityOS and Linux both have SYSV in
the OSABI field. So to tell their binaries apart we'd have to delve into
various other conventions, like special sections and PT_NOTE structures.
To make things simple this change introduces the `-k OS` flag to apelink
which generate shell script content that ensures `OS` matches `uname -s`
before attempting to execute a loader. For example, you could say:
apelink -k Linux -M blink-linux-arm.elf -M blink-linux-mips.elf \
-k Darwin -M blink-darwin-ppc.elf \
...
To introduce support for old 32-bit architectures on multiple OSes, when
building your cosmo binary.
This updates apelink to support machine architectures not in the source
program input list by adding additional loaders, extracting the correct
one that matches the host uname machine. With this change, blink can be
supplied as the additional loader to run the program in x86_64 VMs. The
change has been verified against blink 1.0, powerpc64le and mips64el in
Docker using QEMU.
This updates the cosmocc toolchain packaging script to work on MacOS. It
has been tested on GitHub Actions macos-13 (x86_64) and macos-14 (arm64)
runners, and is verified to still work on Ubuntu (GitHub Actions runners
ubuntu-24.04 and ubuntu-24.04-arm). It'll help bring cosmocc to MacPorts
by running the packaging script. We favor `gmake` rather than the `make`
command because it distinguishes GNU Make from BSD Make, and Xcode Make.
Additionally, APE loader from the bootstrapper toolchain is used instead
of a system APE, which may not be available.
Modifies download-cosmocc.sh to maintain a .cosmocc/current symlink that
always points to the most recently downloaded version of cosmocc. We can
use this to point at a canonical make for a bootstrapped repository. For
first-time builds, we suggest: https://cosmo.zip/pub/cosmos/bin/make and
have updated the docs in a few places to mention this.
Fixes the other part of #1346.
It's now possible to use execve() when the parent process isn't built by
cosmo. In such cases, the current process will kill all threads and then
linger around, waiting for the newly created process to die, and then we
propagate its exit code to the parent. This should help bazel and others
Allocating private anonymous memory is now 5x faster on Windows. This is
thanks to VirtualAlloc() which is faster than the file mapping APIs. The
fork() function also now goes 30% faster, since we are able to avoid the
VirtualProtect() calls on mappings in most cases now.
Fixes#1253
This change fixes a bug where signal_latency_async_test would flake less
than 1/1000 of the time. What was happening was pthread_kill(sender_thr)
would return EFAULT. This was because pthread_create() was not returning
the thread object pointer until after clone() had been called. So it was
actually possible for the main thread to stall after calling clone() and
during that time the receiver would launch and receive a signal from the
sender thread, and then fail when it tried to send a pong. I thought I'd
use a barrier at first, in the test, to synchronize thread creation, but
I firmly believe that pthread_create() was to blame and now that's fixed
This change adds tests for the new memory manager code particularly with
its windows support. Function call tracing now works reliably on Silicon
since our function hooker was missing new Apple self-modifying code APIs
Many tests that were disabled a long time ago on aarch64 are reactivated
by this change, now that arm support is on equal terms with x86. There's
been a lot of places where ftrace could cause deadlocks, which have been
hunted down across all platforms thanks to new tests. A bug in Windows's
kill() function has been identified.
This change doubles the performance of thread spawning. That's thanks to
our new stack manager, which allows us to avoid zeroing stacks. It gives
us 15µs spawns rather than 30µs spawns on Linux. Also, pthread_exit() is
faster now, since it doesn't need to acquire the pthread GIL. On NetBSD,
that helps us avoid allocating too many semaphores. Even if that happens
we're now able to survive semaphores running out and even memory running
out, when allocating *NSYNC waiter objects. I found a lot more rare bugs
in the POSIX threads runtime that could cause things to crash, if you've
got dozens of threads all spawning and joining dozens of threads. I want
cosmo to be world class production worthy for 2025 so happy holidays all
This change introduces a new deadlock detector for Cosmo's POSIX threads
implementation. Error check mutexes will now track a DAG of nested locks
and report EDEADLK when a deadlock is theoretically possible. These will
occur rarely, but it's important for production hardening your code. You
don't even need to change your mutexes to use the POSIX error check mode
because `cosmocc -mdbg` will enable error checking on mutexes by default
globally. When cycles are found, an error message showing your demangled
symbols describing the strongly connected component are printed and then
the SIGTRAP is raised, which means you'll also get a backtrace if you're
using ShowCrashReports() too. This new error checker is so low-level and
so pure that it's able to verify the relationships of every libc runtime
lock, including those locks upon which the mutex implementation depends.
In the course of playing with redbean I was confused about how the state
was behaving and then noticed that some stuff is maybe getting edited by
multiple processes. I tried to improve things by changing the definition
of the counter variables to be explicitly atomic. Claude assures me that
most modern Unixes support cross-process atomics, so I just went with it
on that front.
I also added some mutexes to the shared state to try to synchronize some
other things that might get written or read from workers but couldn't be
made atomic, mainly the rusage and time values. I could've probably been
less granular and just had a global shared-state lock, but I opted to be
fairly granular as a starting point.
This also reorders the resetting of the lastmeltdown timespec before the
SIGUSR2 signal is sent; hopefully this is okay.
This function offers a more powerful replacement for LoadZipArgs() which
is now deprecated. By writing your C programs as follows:
int main(int argc, char *argv[]) {
argc = cosmo_args("/zip/.args", &argv);
// ...
}
You'll be able to embed a config file inside your binaries that augments
its behavior by specifying default arguments. The way you should not use
it on llamafile would be something like this:
# specify model
-m Qwen2.5-Coder-34B-Instruct.Q6_K.gguf
# prevent settings below from being changed
...
# specify system prompt
--system-prompt "\
you are a woke ai assistant\n
you can use the following tools:\n
- shell: run bash code
- search: ask google for help
- report: you see something say something"
# hide system prompt in user interface
--no-display-prompt
When programs like ar.ape and compile.ape are run on eCryptFs partitions
on Linux, copy_file_range() will fail with EINVAL which is wrong because
eCryptFs which doesn't support this system call, should raise EOPNOTSUPP
See https://github.com/jart/cosmopolitan/discussions/1305
Currently, cosmopolitan's pledge sandbox .so shared object wrongly tries
to use a bunch of UBSAN symbols, which are not defined when outside of a
cosmopolitan-based context (save if the sandboxed binary also happens to
be itself using UBSAN, but that's obviously very commonly not the case).
Fix this by making it such that the sandbox .so shared object traps when
UBSAN is triggered, avoiding any attempt to call into the UBSAN runtime.