I don't know whether this is really an issue with gfortran or a screwed setting of my macOS installation, I have macOS 12.0.1 Monterey, Darwin 21.1.0, with XCode 13.1, and a simple file main.f90: program main print *, "42" end program main gfortran -o conftest main.f90 prints 42 in the shell, so to stdout. But when tryng pipe to a file this does not work, the file is always empty, i.e. ./conftest > bla.txt result in an empty file.
Using a C program compiled with the same version (recent trunk with the fix by Iain Sandoe for Monterey) leads to a program that can pipe to a file.
confirmed - I have no idea how to categorise this issue at present. Does gfortran do something special opening/cloning stdin/out/err?
(In reply to Iain Sandoe from comment #2) > confirmed - I have no idea how to categorise this issue at present. > > Does gfortran do something special opening/cloning stdin/out/err? Libfortran does a few things with respect to 0, 1 and 2 file fds. Maybe something it does is something that Darwin no longer likes. This is why I moved it to libfortran component.
The problem is not related to XCode 13.1 which appeared at roughly the same time. On Big Sur with XCode 13.1 still all works as expected.
I checked that the assembler code on macOS Big Sur and Monterey is identical (up to the date in the .ident line). So either the assembler works differently, or one of the routines from the libgfortran (_gfortrran_st_write, _gfortran_set_options, _gfortran_set_args, _gfortran_transfer_character_write) acts differently now.
I had a brief look at some new fails on macOS12 / Darwin21 for gcov. It seems that .mod_term_funcs entries are not being run - so if libgfortran relies on something defined as __attribute__((destructor)) [e.g. to flush file output] that might explain the issue.
(although , the output is fine when not redirected, so perhaps that's irrelevant)
I have checked Ada, C++, C, Objective-C++ and Objective-C and they all behave as expected.
I also tried that for a Fortran program ./a.out | less (pipe to less) works. It's just the redirection that does not work. I'm waiting for the compilation to check whether gfortran 11.2 from Macports shares the same problem.
Reassuringly, the gfortran 11.2 from Macports has the same problem as the gfortran 12.0.0 installed by hand: no redirecting into files.
I can confirm this issue on macOS 12.0.1 and gcc/gfortran 10.2.
I'm not an expert on the I/O system, but could it be that the unit to which the stdout of a compiled Fortran program goes does not provide the unit that the redirect function (now) expects under macOS 12?
Here is a complete strace of a "Hello, world" program on Linux, compiled with -static-libgfortran (to remove some of the shared library loading :-) and executed with $ strace ./a.out > hello.dat execve("./a.out", ["./a.out"], 0x7fff23679850 /* 52 vars */) = 0 brk(NULL) = 0x55795af28000 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffef37f68b0) = -1 EINVAL (Invalid argument) access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=137154, ...}) = 0 mmap(NULL, 137154, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6b9f05a000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\3405\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=104984, ...}) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6b9f058000 mmap(NULL, 107592, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6b9f03d000 mmap(0x7f6b9f040000, 73728, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f6b9f040000 mmap(0x7f6b9f052000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7f6b9f052000 mmap(0x7f6b9f056000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7f6b9f056000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libquadmath.so.0", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200:\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=297784, ...}) = 0 mmap(NULL, 299712, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6b9eff3000 mmap(0x7f6b9eff6000, 184320, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f6b9eff6000 mmap(0x7f6b9f023000, 98304, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x30000) = 0x7f6b9f023000 mmap(0x7f6b9f03b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x47000) = 0x7f6b9f03b000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libm.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\363\0\0\0\0\0\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0644, st_size=1369352, ...}) = 0 mmap(NULL, 1368336, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6b9eea4000 mmap(0x7f6b9eeb3000, 684032, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xf000) = 0x7f6b9eeb3000 mmap(0x7f6b9ef5a000, 618496, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb6000) = 0x7f6b9ef5a000 mmap(0x7f6b9eff1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14c000) = 0x7f6b9eff1000 close(3) = 0 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\360q\2\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68 fstat(3, {st_mode=S_IFREG|0755, st_size=2029224, ...}) = 0 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32, 848) = 32 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\t\233\222%\274\260\320\31\331\326\10\204\276X>\263"..., 68, 880) = 68 mmap(NULL, 2036952, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6b9ecb2000 mprotect(0x7f6b9ecd7000, 1847296, PROT_NONE) = 0 mmap(0x7f6b9ecd7000, 1540096, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f6b9ecd7000 mmap(0x7f6b9ee4f000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19d000) = 0x7f6b9ee4f000 mmap(0x7f6b9ee9a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f6b9ee9a000 mmap(0x7f6b9eea0000, 13528, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f6b9eea0000 close(3) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6b9ecb0000 arch_prctl(ARCH_SET_FS, 0x7f6b9ecb0b80) = 0 mprotect(0x7f6b9ee9a000, 12288, PROT_READ) = 0 mprotect(0x7f6b9eff1000, 4096, PROT_READ) = 0 mprotect(0x7f6b9f03b000, 4096, PROT_READ) = 0 mprotect(0x7f6b9f056000, 4096, PROT_READ) = 0 mprotect(0x557959277000, 4096, PROT_READ) = 0 mprotect(0x7f6b9f0a9000, 4096, PROT_READ) = 0 munmap(0x7f6b9f05a000, 137154) = 0 brk(NULL) = 0x55795af28000 brk(0x55795af49000) = 0x55795af49000 fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x1), ...}) = 0 fstat(1, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 fstat(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0x1), ...}) = 0 rt_sigaction(SIGQUIT, {sa_handler=0x5579592418a0, sa_mask=[QUIT], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGILL, {sa_handler=0x5579592418a0, sa_mask=[ILL], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGABRT, {sa_handler=0x5579592418a0, sa_mask=[ABRT], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGFPE, {sa_handler=0x5579592418a0, sa_mask=[FPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGSEGV, {sa_handler=0x5579592418a0, sa_mask=[SEGV], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGBUS, {sa_handler=0x5579592418a0, sa_mask=[BUS], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGSYS, {sa_handler=0x5579592418a0, sa_mask=[SYS], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGTRAP, {sa_handler=0x5579592418a0, sa_mask=[TRAP], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGXCPU, {sa_handler=0x5579592418a0, sa_mask=[XCPU], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 rt_sigaction(SIGXFSZ, {sa_handler=0x5579592418a0, sa_mask=[XFSZ], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7f6b9ecf8210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0 write(1, "Hello, world!\n", 14) = 14 exit_group(0) = ? +++ exited with 0 +++ I see nothing untoward there, the only times file hande 1 is referenced is by fstat(1, {st_mode=S_IFREG|0664, st_size=0, ...}) = 0 and write(1, "Hello, world!\n", 14) = 14 Is it possible to run an equivalent command on MacOS to see what is going on there?
(In reply to Iain Sandoe from comment #6) > I had a brief look at some new fails on macOS12 / Darwin21 for gcov. > > It seems that .mod_term_funcs entries are not being run - so if libgfortran > relies on something defined as __attribute__((destructor)) [e.g. to flush > file output] that might explain the issue. Well, there is (at the end of main.c) /* Cleanup the runtime library. */ static void __attribute__((destructor)) cleanup (void) { close_units (); } I guess that could be put into main, after the call to __MAIN, instead.
Hmm, to test this further: What does program main use, intrinsic :: iso_fortran_env, only: output_unit write (*,'(A)') 'Hello, world!' flush output_unit end program main yield, does that create the file as expected?
(In reply to Thomas Koenig from comment #14) > (In reply to Iain Sandoe from comment #6) > > I had a brief look at some new fails on macOS12 / Darwin21 for gcov. > > > > It seems that .mod_term_funcs entries are not being run - so if libgfortran > > relies on something defined as __attribute__((destructor)) [e.g. to flush > > file output] that might explain the issue. > > Well, there is (at the end of main.c) > > /* Cleanup the runtime library. */ > > static void __attribute__((destructor)) > cleanup (void) > { > close_units (); > } That would seem a very likely candidate for the issue. NOTE: I have been discussing the non-running of mod_term_funcs with my "downstream" and Apple folks. The consensus is that this is 99.99% likely an unintentional bug that just happens not to show with clang-based toolchains because they queue DTORs on atexit (as does GCC for C++). > I guess that could be put into main, after the call to __MAIN, instead. Well, unless there's a good reason to have it in a DTOR, it makes for a more robust solution to call it directly (there are various other differences that could occur in mixed code bases esp. c++ + fortran even without the Darwin21.1 bug). will try your alternate code later.
(In reply to Thomas Koenig from comment #15) > Hmm, to test this further: What does > > program main > use, intrinsic :: iso_fortran_env, only: output_unit > write (*,'(A)') 'Hello, world!' > flush output_unit > end program main > > yield, does that create the file as expected? yup, indeed it does.
(In reply to Thomas Koenig from comment #13) > Here is a complete strace of a "Hello, world" program on Linux, compiled > with -static-libgfortran (to remove some of the shared library loading :-) > and executed with > > $ strace ./a.out > hello.dat > > execve("./a.out", ["./a.out"], 0x7fff23679850 /* 52 vars */) = 0 > brk(NULL) = 0x55795af28000 > > Is it possible to run an equivalent command on MacOS to see > what is going on there? Seems that dtruss is doing the same under macOS, here I get this output for the Hello, world! program: SYSCALL(args) = return Hello, world!\n access("/AppleInternal/XBS/.isChrooted\0", 0x0, 0x0) = -1 Err#2 bsdthread_register(0x7FF805E18020, 0x7FF805E1800C, 0x2000) = 1073742303 0 shm_open(0x7FF805CE6F5D, 0x0, 0x5CE57BA) = 3 0 fstat64(0x3, 0x7FF7BDDDE820, 0x0) = 0 0 mmap(0x0, 0x2000, 0x1, 0x40001, 0x3, 0x0) = 0x102231000 0 close(0x3) = 0 0 ioctl(0x2, 0x4004667A, 0x7FF7BDDDE8D4) = 0 0 mprotect(0x102238000, 0x1000, 0x0) = 0 0 mprotect(0x10223F000, 0x1000, 0x0) = 0 0 mprotect(0x102240000, 0x1000, 0x0) = 0 0 mprotect(0x102247000, 0x1000, 0x0) = 0 0 mprotect(0x102233000, 0x90, 0x1) = 0 0 mprotect(0x102233000, 0x90, 0x3) = 0 0 mprotect(0x102233000, 0x90, 0x1) = 0 0 mprotect(0x102248000, 0x1000, 0x1) = 0 0 mprotect(0x102249000, 0x90, 0x1) = 0 0 mprotect(0x102249000, 0x90, 0x3) = 0 0 mprotect(0x102249000, 0x90, 0x1) = 0 0 mprotect(0x102233000, 0x90, 0x3) = 0 0 mprotect(0x102233000, 0x90, 0x1) = 0 0 mprotect(0x102248000, 0x1000, 0x3) = 0 0 mprotect(0x102248000, 0x1000, 0x1) = 0 0 issetugid(0x0, 0x0, 0x0) = 0 0 getentropy(0x7FF7BDDDE6D0, 0x20, 0x0) = 0 0 getentropy(0x7FF7BDDDE730, 0x40, 0x0) = 0 0 getpid(0x0, 0x0, 0x0) = 61321 0 stat64("/AppleInternal\0", 0x7FF7BDDDEDF0, 0x0) = -1 Err#2 csops_audittoken(0xEF89, 0x7, 0x7FF7BDDDE920) = -1 Err#22 proc_info(0x2, 0xEF89, 0xD) = 64 0 csops_audittoken(0xEF89, 0x7, 0x7FF7BDDDEA10) = -1 Err#22 sysctlbyname(kern.osvariant_status, 0x15, 0x7FF7BDDDEE40, 0x7FF7BDDDEE38, 0x0) = 0 0 csops(0xEF89, 0x0, 0x7FF7BDDDEE74) = 0 0 fstat64(0x0, 0x7FF7BDDDEBF0, 0x0) = 0 0 fstat64(0x1, 0x7FF7BDDDEBF0, 0x0) = 0 0 fstat64(0x2, 0x7FF7BDDDEBF0, 0x0) = 0 0 mprotect(0x10212F000, 0x100000, 0x1) = 0 0 sigaction(0x3, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x4, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x6, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x8, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0xB, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0xA, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0xC, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x5, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x18, 0x7FF7BDDDFFA8, 0x7FF7BDDDFFD0) = 0 0 sigaction(0x19, 0x7FF7BDDDFFB8, 0x7FF7BDDDFFE0) = 0 0 write(0x1, " Hello, world!\\n\n\0", 0x11) = 17 0
(In reply to Jürgen Reuter from comment #18) > write(0x1, " Hello, world!\\n\n\0", 0x11) = 17 0 Hmm, was this actually the string that you put into the Fortran program, or is something very strange going on here?
(In reply to Iain Sandoe from comment #16) > (In reply to Thomas Koenig from comment #14) > NOTE: I have been discussing the non-running of mod_term_funcs with my > "downstream" and Apple folks. The consensus is that this is 99.99% likely > an unintentional bug that just happens not to show with clang-based > toolchains because they queue DTORs on atexit (as does GCC for C++). > > > I guess that could be put into main, after the call to __MAIN, instead. > > Well, unless there's a good reason to have it in a DTOR, it makes for a more > robust solution to call it directly (there are various other differences > that could occur in mixed code bases esp. c++ + fortran even without the > Darwin21.1 bug). There is always the reason of not breaking compatibility, a quick look at close_units() shows that it is not meant to be called twice, so combining both methods is likely to cause headaches. So, something for the next incompatible libgfortran update, maybe. Maybe flushing all units on program termination would be safer, but I am not sure we should put in a workaround for what appears to be a bug in the underlying system (hopefully soon to be fixed), especially since there seems to be a workaround in user code.
(In reply to Thomas Koenig from comment #19) > (In reply to Jürgen Reuter from comment #18) > > > write(0x1, " Hello, world!\\n\n\0", 0x11) = 17 0 > > Hmm, was this actually the string that you put into the Fortran > program, or is something very strange going on here? Yes, the program was program main print *, "Hello, world!\n" end program main sorry, about the backslash \n, that was accidental. Doing just program main print *, "Hello, world!" end program main # dtruss ./a.out > out.008 SYSCALL(args) = return Hello, world! access("/AppleInternal/XBS/.isChrooted\0", 0x0, 0x0) = -1 Err#2 bsdthread_register(0x7FF805E18020, 0x7FF805E1800C, 0x2000) = 1073742303 0 shm_open(0x7FF805CE6F5D, 0x0, 0x5CE57BA) = 3 0 fstat64(0x3, 0x7FF7BE646820, 0x0) = 0 0 mmap(0x0, 0x2000, 0x1, 0x40001, 0x3, 0x0) = 0x1019C9000 0 close(0x3) = 0 0 ioctl(0x2, 0x4004667A, 0x7FF7BE6468D4) = 0 0 mprotect(0x1019D0000, 0x1000, 0x0) = 0 0 mprotect(0x1019D7000, 0x1000, 0x0) = 0 0 mprotect(0x1019D8000, 0x1000, 0x0) = 0 0 mprotect(0x1019DF000, 0x1000, 0x0) = 0 0 mprotect(0x1019CB000, 0x90, 0x1) = 0 0 mprotect(0x1019CB000, 0x90, 0x3) = 0 0 mprotect(0x1019CB000, 0x90, 0x1) = 0 0 mprotect(0x1019E0000, 0x1000, 0x1) = 0 0 mprotect(0x1019E1000, 0x90, 0x1) = 0 0 mprotect(0x1019E1000, 0x90, 0x3) = 0 0 mprotect(0x1019E1000, 0x90, 0x1) = 0 0 mprotect(0x1019CB000, 0x90, 0x3) = 0 0 mprotect(0x1019CB000, 0x90, 0x1) = 0 0 mprotect(0x1019E0000, 0x1000, 0x3) = 0 0 mprotect(0x1019E0000, 0x1000, 0x1) = 0 0 issetugid(0x0, 0x0, 0x0) = 0 0 getentropy(0x7FF7BE6466D0, 0x20, 0x0) = 0 0 getentropy(0x7FF7BE646730, 0x40, 0x0) = 0 0 getpid(0x0, 0x0, 0x0) = 61408 0 stat64("/AppleInternal\0", 0x7FF7BE646DF0, 0x0) = -1 Err#2 csops_audittoken(0xEFE0, 0x7, 0x7FF7BE646920) = -1 Err#22 proc_info(0x2, 0xEFE0, 0xD) = 64 0 csops_audittoken(0xEFE0, 0x7, 0x7FF7BE646A10) = -1 Err#22 sysctlbyname(kern.osvariant_status, 0x15, 0x7FF7BE646E40, 0x7FF7BE646E38, 0x0) = 0 0 csops(0xEFE0, 0x0, 0x7FF7BE646E74) = 0 0 fstat64(0x0, 0x7FF7BE646BF0, 0x0) = 0 0 fstat64(0x1, 0x7FF7BE646BF0, 0x0) = 0 0 fstat64(0x2, 0x7FF7BE646BF0, 0x0) = 0 0 mprotect(0x1018C7000, 0x100000, 0x1) = 0 0 sigaction(0x3, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x4, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x6, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x8, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0xB, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0xA, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0xC, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x5, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x18, 0x7FF7BE647FA8, 0x7FF7BE647FD0) = 0 0 sigaction(0x19, 0x7FF7BE647FB8, 0x7FF7BE647FE0) = 0 0 write(0x1, " Hello, world!\n\0", 0xF) = 15 0
(In reply to Thomas Koenig from comment #20) > (In reply to Iain Sandoe from comment #16) > > (In reply to Thomas Koenig from comment #14) > > There is always the reason of not breaking compatibility, a quick look > at close_units() shows that it is not meant to be called twice, > so combining both methods is likely to cause headaches. > > So, something for the next incompatible libgfortran update, maybe. > > Maybe flushing all units on program termination would be safer, but > I am not sure we should put in a workaround for what appears to > be a bug in the underlying system (hopefully soon to be fixed), > especially since there seems to be a workaround in user code. I agree that if this an OS bug, then workarounds in libgfortran that might jeopardize the integrity are hard to justify. Do we know that this will be fixed let's say for macOS 12.0.2 or so, and when will that come? At the moment these things do break quite a lot of build scripts for software that rely on redirecting output from test programs. Changing all those test programs to iso_fortan_env is tedious (but doable).
(In reply to Jürgen Reuter from comment #22) > (In reply to Thomas Koenig from comment #20) > > (In reply to Iain Sandoe from comment #16) > > > (In reply to Thomas Koenig from comment #14) > > > > > There is always the reason of not breaking compatibility, a quick look > > at close_units() shows that it is not meant to be called twice, > > so combining both methods is likely to cause headaches. > > > > So, something for the next incompatible libgfortran update, maybe. > > > > Maybe flushing all units on program termination would be safer, but > > I am not sure we should put in a workaround for what appears to > > be a bug in the underlying system (hopefully soon to be fixed), > > especially since there seems to be a workaround in user code. > > I agree that if this an OS bug, then workarounds in libgfortran that might > jeopardize the integrity are hard to justify. Well, we certainly would not want to do compromise integrity, in any event; that would not be a solution. However, ensuring a single call to the function ought to be feasible. the secondary point I made was that the phasing of DTORs called from cxa_atexit (C++) c.f. directly from a destructor can cause subtle issues in any case. >Do we know that this will be > fixed let's say for macOS 12.0.2 or so, and when will that come? I have filed a bug report, (FB9733712). It is impossible to know what the OS release priorities are (or schedules), but I do know that the Apple OSS folks are very supportive of gfortran, so I expect they will help. > At the > moment these things do break quite a lot of build scripts for software that > rely on redirecting output from test programs. Changing all those test > programs to iso_fortan_env is tedious (but doable).
(In reply to Iain Sandoe from comment #23) > (In reply to Jürgen Reuter from comment #22) > > (In reply to Thomas Koenig from comment #20) > > > (In reply to Iain Sandoe from comment #16) > > > > (In reply to Thomas Koenig from comment #14) > > >Do we know that this will be > > fixed let's say for macOS 12.0.2 or so, and when will that come? > > I have filed a bug report, (FB9733712). It is impossible to know what the > OS release priorities are (or schedules), but I do know that the Apple OSS > folks are very supportive of gfortran, so I expect they will help. > Could you post the link to this bug report? I cannot find it. Or is this not publicly visible. > > At the > > moment these things do break quite a lot of build scripts for software that > > rely on redirecting output from test programs. Changing all those test > > programs to iso_fortan_env is tedious (but doable). I just started to look a bit, changing all of your configure script would be really tedious. So I really would prefer a fixed OS or a workaround inside gcc/gfortran.
(In reply to Jürgen Reuter from comment #24) > (In reply to Iain Sandoe from comment #23) > > I have filed a bug report, (FB9733712). It is impossible to know what the > > OS release priorities are (or schedules), but I do know that the Apple OSS > > folks are very supportive of gfortran, so I expect they will help. > Could you post the link to this bug report? I cannot find it. Or is this not > publicly visible. "radars" are not publicly visible, but the ID is significant if you are reporting something to Apple / an Apple OSS person.
(In reply to Iain Sandoe from comment #25) > (In reply to Jürgen Reuter from comment #24) > > (In reply to Iain Sandoe from comment #23) > > > > I have filed a bug report, (FB9733712). It is impossible to know what the > > > OS release priorities are (or schedules), but I do know that the Apple OSS > > > folks are very supportive of gfortran, so I expect they will help. > > > Could you post the link to this bug report? I cannot find it. Or is this not > > publicly visible. > > "radars" are not publicly visible, but the ID is significant if you are > reporting something to Apple / an Apple OSS person. I added to the openradars site here: https://openradar.appspot.com/FB9733712 (that doesn't make any difference to visibility of if/when it will be fixed, of course)
*** Bug 103043 has been marked as a duplicate of this bug. ***
> Well, unless there's a good reason to have it in a DTOR, it makes for a more > robust solution to call it directly (there are various other differences > that could occur in mixed code bases esp. c++ + fortran even without the > Darwin21.1 bug). Mixed code is in fact the reason why it's in a DTOR and not called at the end of Fortran main program. We need this clean-up routine to run even when the main code is not in Fortran, and but Fortran routines are called by other means (Fortran object files linked, or Fortran-based library loaded at run-time).
(In reply to Francois-Xavier Coudert from comment #28) > > Well, unless there's a good reason to have it in a DTOR, it makes for a more > > robust solution to call it directly (there are various other differences > > that could occur in mixed code bases esp. c++ + fortran even without the > > Darwin21.1 bug). > > Mixed code is in fact the reason why it's in a DTOR and not called at the > end of Fortran main program. We need this clean-up routine to run even when > the main code is not in Fortran, and but Fortran routines are called by > other means (Fortran object files linked, or Fortran-based library loaded at > run-time). I've posted a fix for this (it is the fix for darwin21 DTORs in general) however CAVEAT : there is No guarantee given by the GCC DTOR machinery about the relative ordering of DTORs between different TUs, my fix will not solve that.
(In reply to Iain Sandoe from comment #29) > I've posted a fix for this (it is the fix for darwin21 DTORs in general) Yes I've seen the patch, thanks! > however CAVEAT : there is No guarantee given by the GCC DTOR machinery about > the relative ordering of DTORs between different TUs, my fix will not solve > that. That was already the case before (if I understand right) and this is fine for our use: we have only one DTOR in libgfortran, and Fortran I/O and I/O in other languages should not operate on the same files or descriptors.
(In reply to Iain Sandoe from comment #29) > (In reply to Francois-Xavier Coudert from comment #28) > I've posted a fix for this (it is the fix for darwin21 DTORs in general) > however CAVEAT : there is No guarantee given by the GCC DTOR machinery about > the relative ordering of DTORs between different TUs, my fix will not solve > that. Does this now mean that this is fixed within the gcc trunk/master? Or just in a branch which has yet to be merged into the master? And will it be backported for 11.3, 10.4 as well?
(In reply to Jürgen Reuter from comment #31) > Does this now mean that this is fixed within the gcc trunk/master? Or just in > a branch which has yet to be merged into the master? The patch was posted for review, and okayed on 13 November at https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584359.html
The master branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:fabe8cc41e9b01913e2016861237d1d99d7567bf commit r12-5281-gfabe8cc41e9b01913e2016861237d1d99d7567bf Author: Iain Sandoe <iain@sandoe.co.uk> Date: Thu Nov 4 09:37:14 2021 +0000 IPA: Provide a mechanism to register static DTORs via cxa_atexit. For at least one target (Darwin) the platform convention is to register static destructors (i.e. __attribute__((destructor))) with __cxa_atexit rather than placing them into a list that is run by some other mechanism. This patch provides a target hook that allows a target to opt into this and handling for the process in ipa_cdtor_merge (). When the mode is enabled (dtors_from_cxa_atexit is set) we: * Generate new CTORs to register static destructors with __cxa_atexit and add them to the existing list of CTORs; we then process the revised CTORs list. * We sort the DTORs into priority and then TU order, this means that they are registered in that order with __cxa_atexit () and therefore will be run in the reverse order. * Likewise, CTORs are sorted into priority and then TU order, which means that they will run in that order. This matches the behavior of using init/fini (or mod_init_func/mod_term_func) sections. This also fixes a bug where Fortran needs a DTOR to be run to close IO. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR fortran/102992 gcc/ChangeLog: * config/darwin.h (TARGET_DTORS_FROM_CXA_ATEXIT): New. * doc/tm.texi: Regenerated. * doc/tm.texi.in: Add TARGET_DTORS_FROM_CXA_ATEXIT hook. * ipa.c (cgraph_build_static_cdtor_1): Return the built function decl. (build_cxa_atexit_decl): New. (build_dso_handle_decl): New. (build_cxa_dtor_registrations): New. (compare_cdtor_tu_order): New. (build_cxa_atexit_fns): New. (ipa_cdtor_merge): If dtors_from_cxa_atexit is set, process the DTORs/CTORs accordingly. (pass_ipa_cdtor_merge::gate): Also run if dtors_from_cxa_atexit is set. * target.def (dtors_from_cxa_atexit): New hook.
I did ask for OK on back-ports We should let it bake on master for now - I see reports that 12.1 ia under test - but no idea when it will come out (or if this particular issue will be fixed in it). In any event, it was designed to be an add-on so that the behaviour of everything else (that does not set the target option) would be unchanged - so IMO it would be safe to use the back ported patch ahead of "reality" in emergency.
Now that macOS 12.1 is out (and XCode 13.2) could someone please check whether the problem has been solved from the side of the Darwin kernel?
(In reply to Jürgen Reuter from comment #35) > Now that macOS 12.1 is out (and XCode 13.2) could someone please check > whether the problem has been solved from the side of the Darwin kernel? I didn't see the issue listed in the 12.1 description and my radar is not acknowledged officially (although some of the OSS folks agree it is a bug). So .. right now I would not expect it to be resolved without the master change and I intend to back port that change too - since clang sets the effective ABI, it is more compatible for us to use the same approach (even if the term funcs would work in principle). Note 103080 also (and I would think that impossible to solve without using the current approach of registering on cxa-atexit).
OS bug confirmed to be still present on macOS 12.1 (darwin 21.2.0), at least on Intel. I don't have a non-patched compiler on ARM right now to confirm, but I don't expect it to be arch-dependent.
The releases/gcc-11 branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:6841e9fc63b260186f8c980c7e0534b6376b073f commit r11-9873-g6841e9fc63b260186f8c980c7e0534b6376b073f Author: Iain Sandoe <iain@sandoe.co.uk> Date: Thu Nov 4 09:37:14 2021 +0000 IPA: Provide a mechanism to register static DTORs via cxa_atexit. For at least one target (Darwin) the platform convention is to register static destructors (i.e. __attribute__((destructor))) with __cxa_atexit rather than placing them into a list that is run by some other mechanism. This patch provides a target hook that allows a target to opt into this and handling for the process in ipa_cdtor_merge (). When the mode is enabled (dtors_from_cxa_atexit is set) we: * Generate new CTORs to register static destructors with __cxa_atexit and add them to the existing list of CTORs; we then process the revised CTORs list. * We sort the DTORs into priority and then TU order, this means that they are registered in that order with __cxa_atexit () and therefore will be run in the reverse order. * Likewise, CTORs are sorted into priority and then TU order, which means that they will run in that order. This matches the behavior of using init/fini (or mod_init_func/mod_term_func) sections. This also fixes a bug where Fortran needs a DTOR to be run to close IO. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR fortran/102992 gcc/ChangeLog: * config/darwin.h (TARGET_DTORS_FROM_CXA_ATEXIT): New. * doc/tm.texi: Regenerated. * doc/tm.texi.in: Add TARGET_DTORS_FROM_CXA_ATEXIT hook. * ipa.c (cgraph_build_static_cdtor_1): Return the built function decl. (build_cxa_atexit_decl): New. (build_dso_handle_decl): New. (build_cxa_dtor_registrations): New. (compare_cdtor_tu_order): New. (build_cxa_atexit_fns): New. (ipa_cdtor_merge): If dtors_from_cxa_atexit is set, process the DTORs/CTORs accordingly. (pass_ipa_cdtor_merge::gate): Also run if dtors_from_cxa_atexit is set. * target.def (dtors_from_cxa_atexit): New hook. (cherry picked from commit fabe8cc41e9b01913e2016861237d1d99d7567bf)
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
The releases/gcc-10 branch has been updated by Iain D Sandoe <iains@gcc.gnu.org>: https://gcc.gnu.org/g:16db663772c03eded30d8ede7ffbc2b9de25f648 commit r10-10802-g16db663772c03eded30d8ede7ffbc2b9de25f648 Author: Iain Sandoe <iain@sandoe.co.uk> Date: Thu Nov 4 09:37:14 2021 +0000 IPA: Provide a mechanism to register static DTORs via cxa_atexit. For at least one target (Darwin) the platform convention is to register static destructors (i.e. __attribute__((destructor))) with __cxa_atexit rather than placing them into a list that is run by some other mechanism. This patch provides a target hook that allows a target to opt into this and handling for the process in ipa_cdtor_merge (). When the mode is enabled (dtors_from_cxa_atexit is set) we: * Generate new CTORs to register static destructors with __cxa_atexit and add them to the existing list of CTORs; we then process the revised CTORs list. * We sort the DTORs into priority and then TU order, this means that they are registered in that order with __cxa_atexit () and therefore will be run in the reverse order. * Likewise, CTORs are sorted into priority and then TU order, which means that they will run in that order. This matches the behavior of using init/fini (or mod_init_func/mod_term_func) sections. This also fixes a bug where Fortran needs a DTOR to be run to close IO. Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> PR fortran/102992 gcc/ChangeLog: * config/darwin.h (TARGET_DTORS_FROM_CXA_ATEXIT): New. * doc/tm.texi: Regenerated. * doc/tm.texi.in: Add TARGET_DTORS_FROM_CXA_ATEXIT hook. * ipa.c (cgraph_build_static_cdtor_1): Return the built function decl. (build_cxa_atexit_decl): New. (build_dso_handle_decl): New. (build_cxa_dtor_registrations): New. (compare_cdtor_tu_order): New. (build_cxa_atexit_fns): New. (ipa_cdtor_merge): If dtors_from_cxa_atexit is set, process the DTORs/CTORs accordingly. (pass_ipa_cdtor_merge::gate): Also run if dtors_from_cxa_atexit is set. * target.def (dtors_from_cxa_atexit): New hook. (cherry picked from commit fabe8cc41e9b01913e2016861237d1d99d7567bf)
fixed for open branches, the equivalent is needed to build working compilers on darwin21 for earlier gcc versions.