libeatmydata
libeatmydata copied to clipboard
eatmydata doesn't seem to work on macos
Thanks to a tip-off from @carlocab I did a simple test to see if eatmydata actually eats my data on macos:
eatmydata
relies onDYLD_FORCE_FLAT_NAMESPACE
andDYLD_INSERT_LIBRARIES
, which, in my experience, no longer works on newer versions of macOS.
The trick I used relies on eatmydata (quite reasonably IMHO) not attempting to emulate the error case where the fd isn't actually syncable. So this test program behaves differently when under eatmydata vs not:
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main() {
int fd;
for (fd = 0; fd <= 2; ++fd) {
int r = fsync(fd);
if (r != 0) {
printf("fsync of fd %d failed: %s\n", fd, strerror(errno));
}
#ifdef __APPLE__
r = fcntl(fd, F_FULLFSYNC, 0);
if (r != 0) {
printf("F_FULLFSYNC of fd %d failed: %s\n", fd, strerror(errno));
}
#endif
}
return 0;
}
Testing on Debian unstable, using the debian eatmydata package:
$ gcc -Wall -W -O2 testeatmydata.c -o testeatmydata
$ ./testeatmydata < /dev/null 2> /dev/null
fsync of fd 0 failed: Invalid argument
fsync of fd 1 failed: Invalid argument
fsync of fd 2 failed: Invalid argument
$ eatmydata ./testeatmydata < /dev/null 2> /dev/null
$
This demonstrates that this error case is indeed handled differently when eatmydata is working. So far, so good.
I don't own a mac, so I tested macos using github actions - this is using the homebrew libeatmydata package which includes the patch from #33 that you kindly recently merged:
https://github.com/ojwb/homebrew-eatmydata-test/actions/runs/5766706912/job/15635169095
The output from ./testeatmydata < /dev/null 2> /dev/null
is exactly the same with and without eatmydata
:
F_FULLFSYNC of fd 0 failed: Operation not supported by device
fsync of fd 1 failed: Operation not supported
F_FULLFSYNC of fd 1 failed: Bad file descriptor
F_FULLFSYNC of fd 2 failed: Operation not supported by device
With a working eatmydata I would expect the output to differ, probably with no errors reported under eatmydata though I find F_FULLFSYNC of fd 1 failed: Bad file descriptor
surprising as stdout must be open for this output to get logged - I'd guess it's a socket (fds 0 and 2 should be block devices).
I'm afraid I don't know how to fix this.
It occurred to me to look at other preload libraries, and the first one I looked at was libfaketime which seems to provide the solution:
https://github.com/wolfcw/libfaketime/commit/ee4f57d8a581fe2fb826d820954eecc0c33e8724