Created
March 6, 2026 23:19
-
-
Save jhoblitt/9ce718b3d0e9cbc15acc6946287bc757 to your computer and use it in GitHub Desktop.
chatgpt's attempt to preproduce the git 2.52.0 clone failure seen on ganesha v9.4/v9.6 exports
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE | |
| #include <errno.h> | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| #include <stdbool.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/mman.h> | |
| #include <sys/stat.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
| static const char *CONFIG_PATH = "config"; | |
| static const char *LOCK_PATH = "config.lock"; | |
| static void die(const char *msg) { | |
| perror(msg); | |
| exit(1); | |
| } | |
| static void safe_close(int fd, const char *what) { | |
| if (close(fd) != 0) { | |
| perror(what); | |
| exit(1); | |
| } | |
| } | |
| static void write_full(int fd, const void *buf, size_t len, const char *what) { | |
| const char *p = buf; | |
| size_t off = 0; | |
| while (off < len) { | |
| ssize_t n = write(fd, p + off, len - off); | |
| if (n < 0) { | |
| perror(what); | |
| exit(1); | |
| } | |
| off += (size_t)n; | |
| } | |
| } | |
| static void dump_hex(const void *buf, size_t len) { | |
| const unsigned char *p = buf; | |
| for (size_t i = 0; i < len; i++) { | |
| printf("%02x", p[i]); | |
| if ((i + 1) % 16 == 0 || i + 1 == len) | |
| printf("\n"); | |
| else | |
| printf(" "); | |
| } | |
| } | |
| static void write_config_atomically(const char *content, size_t len, bool do_fsync) { | |
| unlink(LOCK_PATH); | |
| int fd = open(LOCK_PATH, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0666); | |
| if (fd < 0) | |
| die("open config.lock"); | |
| if (fchmod(fd, 0644) != 0) | |
| die("fchmod config.lock"); | |
| write_full(fd, content, len, "write config.lock"); | |
| if (do_fsync) { | |
| if (fsync(fd) != 0) | |
| die("fsync config.lock"); | |
| } | |
| safe_close(fd, "close config.lock"); | |
| if (rename(LOCK_PATH, CONFIG_PATH) != 0) | |
| die("rename config.lock -> config"); | |
| } | |
| static void read_once_or_report(int iter, const char *expected, size_t expected_len) { | |
| int fd = open(CONFIG_PATH, O_RDONLY); | |
| if (fd < 0) | |
| die("open config for read"); | |
| char buf[4096]; | |
| memset(buf, 0, sizeof(buf)); | |
| ssize_t n = read(fd, buf, 1024); | |
| if (n < 0) { | |
| fprintf(stderr, | |
| "\nITER %d: read(config) failed: errno=%d (%s)\n", | |
| iter, errno, strerror(errno)); | |
| safe_close(fd, "close config after failed read"); | |
| exit(2); | |
| } | |
| off_t off = lseek(fd, 0, SEEK_CUR); | |
| if (off == (off_t)-1) | |
| die("lseek after read"); | |
| printf("iter=%d simple-read: n=%zd off=%lld\n", | |
| iter, n, (long long)off); | |
| if ((size_t)n != expected_len || memcmp(buf, expected, expected_len) != 0) { | |
| fprintf(stderr, "\nITER %d: content mismatch\n", iter); | |
| fprintf(stderr, "expected_len=%zu got=%zd\n", expected_len, n); | |
| fprintf(stderr, "expected:\n%.*s\n", (int)expected_len, expected); | |
| fprintf(stderr, "got:\n%.*s\n", (int)n, buf); | |
| fprintf(stderr, "got hex:\n"); | |
| dump_hex(buf, (size_t)n); | |
| safe_close(fd, "close config after mismatch"); | |
| exit(3); | |
| } | |
| safe_close(fd, "close config after read"); | |
| } | |
| static void git_like_read_mmap_copy(int iter) { | |
| unlink(LOCK_PATH); | |
| int lockfd = open(LOCK_PATH, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0666); | |
| if (lockfd < 0) | |
| die("open lockfd for git-like copy"); | |
| if (fchmod(lockfd, 0644) != 0) | |
| die("fchmod lockfd"); | |
| int fd1 = open(CONFIG_PATH, O_RDONLY); | |
| if (fd1 < 0) | |
| die("open fd1"); | |
| int fd2 = open(CONFIG_PATH, O_RDONLY); | |
| if (fd2 < 0) | |
| die("open fd2"); | |
| char tmp[1024]; | |
| ssize_t rn; | |
| struct stat st; | |
| if (fstat(fd2, &st) != 0) | |
| die("fstat fd2"); | |
| rn = read(fd2, tmp, sizeof(tmp)); | |
| if (rn < 0) { | |
| fprintf(stderr, | |
| "\nITER %d: git-like read(fd2) failed: errno=%d (%s)\n", | |
| iter, errno, strerror(errno)); | |
| safe_close(fd2, "close fd2 after failed read"); | |
| safe_close(fd1, "close fd1 after failed read"); | |
| safe_close(lockfd, "close lockfd after failed read"); | |
| exit(4); | |
| } | |
| printf("iter=%d git-like read(fd2): n=%zd st_size=%lld\n", | |
| iter, rn, (long long)st.st_size); | |
| safe_close(fd2, "close fd2"); | |
| if (fstat(fd1, &st) != 0) | |
| die("fstat fd1"); | |
| void *addr = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd1, 0); | |
| if (addr == MAP_FAILED) | |
| die("mmap fd1"); | |
| safe_close(fd1, "close fd1"); | |
| write_full(lockfd, "[core]\n", 7, "write prefix 1"); | |
| write_full(lockfd, "\tbare = false\n", 14, "write prefix 2"); | |
| ssize_t wn = write(lockfd, addr, (size_t)st.st_size); | |
| if (wn < 0) { | |
| fprintf(stderr, | |
| "\nITER %d: git-like write(lockfd, mmap_addr) failed: errno=%d (%s)\n", | |
| iter, errno, strerror(errno)); | |
| munmap(addr, (size_t)st.st_size); | |
| safe_close(lockfd, "close lockfd after failed mmap write"); | |
| exit(5); | |
| } | |
| printf("iter=%d git-like mmap-copy write: n=%zd\n", iter, wn); | |
| if (munmap(addr, (size_t)st.st_size) != 0) | |
| die("munmap"); | |
| safe_close(lockfd, "close lockfd"); | |
| } | |
| int main(int argc, char **argv) { | |
| int iterations = 1000; | |
| bool do_fsync = false; | |
| bool do_git_like = true; | |
| if (argc > 1) | |
| iterations = atoi(argv[1]); | |
| if (argc > 2) | |
| do_fsync = (atoi(argv[2]) != 0); | |
| if (argc > 3) | |
| do_git_like = (atoi(argv[3]) != 0); | |
| const char *content1 = | |
| "[core]\n" | |
| "\trepositoryformatversion = 0\n"; | |
| const char *content2 = | |
| "[core]\n" | |
| "\trepositoryformatversion = 0\n" | |
| "\tfilemode = true\n"; | |
| size_t len1 = strlen(content1); | |
| size_t len2 = strlen(content2); | |
| unlink(CONFIG_PATH); | |
| unlink(LOCK_PATH); | |
| for (int i = 1; i <= iterations; i++) { | |
| const char *content = (i & 1) ? content1 : content2; | |
| size_t len = (i & 1) ? len1 : len2; | |
| printf("\n=== iter %d write len=%zu ===\n", i, len); | |
| write_config_atomically(content, len, do_fsync); | |
| read_once_or_report(i, content, len); | |
| if (do_git_like) | |
| git_like_read_mmap_copy(i); | |
| } | |
| printf("\ncompleted %d iterations without failure\n", iterations); | |
| return 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| rook-ceph-demo-nfs-auxtel-jhoblitt-test1:/data/auxtel/gittest$ strace ./c.out | |
| execve("./c.out", ["./c.out"], 0x7ffc4ab71440 /* 16 vars */) = 0 | |
| arch_prctl(ARCH_SET_FS, 0x7f8bad9687b8) = 0 | |
| set_tid_address(0x7f8bad9688f0) = 600 | |
| brk(NULL) = 0x42b000 | |
| brk(0x42c000) = 0x42c000 | |
| readlink("/proc/self/exe", "/data/auxtel/gittest/c.out", 4096) = 26 | |
| execve("/lib/ld-musl-x86_64.so.1", ["ld-linux-x86-64.so.2", "--argv0", "./c.out", "--preload", "/lib/libgcompat.so.0 ", "--", "/data/auxtel/gittest/c.out"], 0x7ffd6b647dc8 /* 16 vars */) = 0 | |
| arch_prctl(ARCH_SET_FS, 0x7f520c409b28) = 0 | |
| set_tid_address(0x7f520c409f90) = 600 | |
| open("/data/auxtel/gittest/c.out", O_RDONLY|O_LARGEFILE) = 3 | |
| read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0\360\4@\0\0\0\0\0"..., 960) = 960 | |
| mmap(0x400000, 16384, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x400000 | |
| mmap(0x401000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x401000 | |
| mmap(0x402000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x402000 | |
| close(3) = 0 | |
| brk(NULL) = 0x555556ead000 | |
| brk(0x555556eaf000) = 0x555556eaf000 | |
| mmap(0x555556ead000, 4096, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x555556ead000 | |
| open("/lib/libgcompat.so.0", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fstat(3, {st_mode=S_IFREG|0755, st_size=67184, ...}) = 0 | |
| read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 960) = 960 | |
| mmap(NULL, 73728, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f520c352000 | |
| mmap(0x7f520c359000, 20480, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0x7000) = 0x7f520c359000 | |
| mmap(0x7f520c35e000, 12288, PROT_READ, MAP_PRIVATE|MAP_FIXED, 3, 0xc000) = 0x7f520c35e000 | |
| mmap(0x7f520c361000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f520c361000 | |
| mmap(0x7f520c363000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f520c363000 | |
| close(3) = 0 | |
| open("/etc/ld-musl-x86_64.path", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) | |
| open("/lib/libucontext.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) | |
| open("/usr/local/lib/libucontext.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) | |
| open("/usr/lib/libucontext.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fstat(3, {st_mode=S_IFREG|0755, st_size=13936, ...}) = 0 | |
| read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 960) = 960 | |
| mmap(NULL, 20480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f520c34d000 | |
| mmap(0x7f520c34e000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x7f520c34e000 | |
| mmap(0x7f520c34f000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED, 3, 0x2000) = 0x7f520c34f000 | |
| mmap(0x7f520c350000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x2000) = 0x7f520c350000 | |
| close(3) = 0 | |
| open("/lib/libobstack.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) | |
| open("/usr/local/lib/libobstack.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = -1 ENOENT (No such file or directory) | |
| open("/usr/lib/libobstack.so.1", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fstat(3, {st_mode=S_IFREG|0755, st_size=13944, ...}) = 0 | |
| read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 960) = 960 | |
| mmap(NULL, 20480, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f520c348000 | |
| mmap(0x7f520c349000, 4096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x7f520c349000 | |
| mmap(0x7f520c34a000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED, 3, 0x2000) = 0x7f520c34a000 | |
| mmap(0x7f520c34b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x2000) = 0x7f520c34b000 | |
| close(3) = 0 | |
| mprotect(0x7f520c361000, 4096, PROT_READ) = 0 | |
| mprotect(0x7f520c406000, 4096, PROT_READ) = 0 | |
| mprotect(0x7f520c350000, 4096, PROT_READ) = 0 | |
| mprotect(0x7f520c34b000, 4096, PROT_READ) = 0 | |
| mprotect(0x402000, 4096, PROT_READ) = 0 | |
| unlink("config") = 0 | |
| unlink("config.lock") = -1 ENOENT (No such file or directory) | |
| ioctl(1, TIOCGWINSZ, {ws_row=48, ws_col=190, ws_xpixel=0, ws_ypixel=0}) = 0 | |
| writev(1, [{iov_base="\n", iov_len=1}], 1 | |
| ) = 1 | |
| writev(1, [{iov_base="=== iter 1 write len=36", iov_len=23}, {iov_base=" ===\n", iov_len=5}], 2=== iter 1 write len=36 === | |
| ) = 28 | |
| unlink("config.lock") = -1 ENOENT (No such file or directory) | |
| open("config.lock", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE|O_CLOEXEC, 0666) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fchmod(3, 0644) = 0 | |
| write(3, "[core]\n\trepositoryformatversion "..., 36) = 36 | |
| close(3) = 0 | |
| rename("config.lock", "config") = 0 | |
| open("config", O_RDONLY|O_LARGEFILE) = 3 | |
| read(3, "[core]\n\trepositoryformatversion "..., 1024) = 36 | |
| lseek(3, 0, SEEK_CUR) = 36 | |
| writev(1, [{iov_base="iter=1 simple-read: n=36 off=36", iov_len=31}, {iov_base="\n", iov_len=1}], 2iter=1 simple-read: n=36 off=36 | |
| ) = 32 | |
| close(3) = 0 | |
| unlink("config.lock") = -1 ENOENT (No such file or directory) | |
| open("config.lock", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE|O_CLOEXEC, 0666) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fchmod(3, 0644) = 0 | |
| open("config", O_RDONLY|O_LARGEFILE) = 4 | |
| open("config", O_RDONLY|O_LARGEFILE) = 5 | |
| fstat(5, {st_mode=S_IFREG|0644, st_size=36, ...}) = 0 | |
| read(5, "[core]\n\trepositoryformatversion "..., 1024) = 36 | |
| writev(1, [{iov_base="iter=1 git-like read(fd2): n=36 "..., iov_len=42}, {iov_base="\n", iov_len=1}], 2iter=1 git-like read(fd2): n=36 st_size=36 | |
| ) = 43 | |
| close(5) = 0 | |
| fstat(4, {st_mode=S_IFREG|0644, st_size=36, ...}) = 0 | |
| mmap(NULL, 36, PROT_READ, MAP_PRIVATE, 4, 0) = 0x7f520c347000 | |
| close(4) = 0 | |
| write(3, "[core]\n", 7) = 7 | |
| write(3, "\tbare = false\n", 14) = 14 | |
| write(3, "[core]\n\trepositoryformatversion "..., 36) = 36 | |
| writev(1, [{iov_base="iter=1 git-like mmap-copy write:"..., iov_len=37}, {iov_base="\n", iov_len=1}], 2iter=1 git-like mmap-copy write: n=36 | |
| ) = 38 | |
| munmap(0x7f520c347000, 36) = 0 | |
| close(3) = 0 | |
| writev(1, [{iov_base="\n", iov_len=1}], 1 | |
| ) = 1 | |
| writev(1, [{iov_base="=== iter 2 write len=53", iov_len=23}, {iov_base=" ===\n", iov_len=5}], 2=== iter 2 write len=53 === | |
| ) = 28 | |
| unlink("config.lock") = 0 | |
| open("config.lock", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE|O_CLOEXEC, 0666) = 3 | |
| fcntl(3, F_SETFD, FD_CLOEXEC) = 0 | |
| fchmod(3, 0644) = 0 | |
| write(3, "[core]\n\trepositoryformatversion "..., 53) = 53 | |
| close(3) = 0 | |
| rename("config.lock", "config") = 0 | |
| open("config", O_RDONLY|O_LARGEFILE) = 3 | |
| read(3, 0x7fffacf4b590, 1024) = -1 EIO (I/O error) | |
| writev(2, [{iov_base="\nITER 2: read(config) failed: er"..., iov_len=50}, {iov_base=NULL, iov_len=0}], 2 | |
| ITER 2: read(config) failed: errno=5 (I/O error) | |
| ) = 50 | |
| close(3) = 0 | |
| exit_group(2) = ? | |
| +++ exited with 2 +++ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment