When I run a program compiled with -fprofile-generate, this program creates a .gcda file, but write/close errors are not checked. With GCC 12.0.0 20210729 built from master and an almost full file system for the .gcda file: $ gcc-test -O -fprofile-generate=dir tst.c $ strace ./a.out [...] openat(AT_FDCWD, "dir/#home#vlefevre#a-tst.gcda", O_RDWR|O_CREAT, 0666) = 3 fcntl(3, F_SETLKW, {l_type=F_WRLCK, l_whence=SEEK_SET, l_start=0, l_len=0}) = 0 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 read(3, "", 1024) = 0 lseek(3, 0, SEEK_SET) = 0 write(3, "adcg 02B\21\20\217\20\0\0\0\241\10\0\0\0\1\0\0\0\1\0\0\0\0\0\0\1"..., 84) = -1 ENOSPC (No space left on device) close(3) = 0 exit_group(0) = ? +++ exited with 0 +++ Note that with gcc (Debian 10.2.1-6) 10.2.1 20210110, I get an error message: $ ./a.out libgcov profiling error:dir/#home#vlefevre#tst.gcda:Error writing but the exit status is also 0, so that the error cannot be detected in scripts.
The question is what to do, exit() or alternatively simply stop attempting to write to the file? (or even remove it)
An immediate exit() might yield other files, the terminal, etc. in a bad state. IMHO, the best thing to do is to stop attempting to write to the file (possibly attempt to remove it, but this might fail), and at the end, exit() with a nonzero exit status.
Note we have a env variable that can achieve an immediate exit (GCOV_EXIT_AT_ERROR): https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Gcov-and-Optimization.html in that case, 1 is the exit code.
GCOV_EXIT_AT_ERROR is not documented in the man page. Anyway, it doesn't seem to work: $ export GCOV_EXIT_AT_ERROR=1 $ printenv GCOV_EXIT_AT_ERROR 1 $ gcc-test -O -fprofile-generate=dir tst.c $ ./a.out $ echo $? 0 $ ls -l dir/*.gcda -rw-r--r-- 1 vlefevre vlefevre 0 2021-08-04 14:48:01 dir/#home#vlefevre#a-tst.gcda
(In reply to Vincent Lefèvre from comment #4) > GCOV_EXIT_AT_ERROR is not documented in the man page. But we document that in GCC user manual. > > Anyway, it doesn't seem to work: > > $ export GCOV_EXIT_AT_ERROR=1 > $ printenv GCOV_EXIT_AT_ERROR > 1 > $ gcc-test -O -fprofile-generate=dir tst.c > $ ./a.out > $ echo $? > 0 > $ ls -l dir/*.gcda > -rw-r--r-- 1 vlefevre vlefevre 0 2021-08-04 14:48:01 > dir/#home#vlefevre#a-tst.gcda It works for me: $ gcc --version gcc (GCC) 12.0.0 20210804 (experimental) $ df -h /tmp/ramdisk Filesystem Size Used Avail Use% Mounted on tmpfs 4.0K 4.0K 0 100% /tmp/ramdisk $ g++ ~/Programming/tramp3d/tramp3d-v4.ii -fprofile-generate=/tmp/ramdisk $ GCOV_EXIT_AT_ERROR=1 ./a.out -n 0 ... libgcov profiling error:/tmp/ramdisk/#home#marxin#Programming#testcases#a-tramp3d-v4.gcda:Error writing profiling:exiting after an error $ echo $? 1 $ ./a.out -n 0 ... libgcov profiling error:/tmp/ramdisk/#home#marxin#Programming#testcases#a-tramp3d-v4.gcda:Error writing echo $? 0
Created attachment 51259 [details] added missing error check on fclose in gcc/gcov-io.c Well, not all errors are detected. There is a missing test in gcc/gcov-io.c for fclose (which does a write system call to flush the buffers): --- a/gcc/gcov-io.c +++ b/gcc/gcov-io.c @@ -199,7 +199,8 @@ gcov_close (void) { if (gcov_var.file) { - fclose (gcov_var.file); + if (fclose (gcov_var.file)) + gcov_var.error = 1; gcov_var.file = 0; } gcov_var.mode = 0; (also in attachment). I've tested this patch, and it solves my problem: openat(AT_FDCWD, "dir/#home#vlefevre#a-tst.gcda", O_RDWR|O_CREAT, 0666) = 3 fcntl(3, F_SETLKW, {l_type=F_WRLCK, l_whence=SEEK_SET, l_start=0, l_len=0}) = 0 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) fstat(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 read(3, "", 1024) = 0 lseek(3, 0, SEEK_SET) = 0 write(3, "adcg 02B\233\10\222\21\0\0\0\241\10\0\0\0\1\0\0\0\1\0\0\0\0\0\0\1"..., 84) = -1 ENOSPC (No space left on device) close(3) = 0 write(2, "libgcov profiling error:dir/#hom"..., 68libgcov profiling error:dir/#home#vlefevre#a-tst.gcda:Error writing ) = 68 write(2, "profiling:exiting after an error"..., 33profiling:exiting after an error ) = 33 exit_group(1) = ? +++ exited with 1 +++
(In reply to Vincent Lefèvre from comment #6) > Created attachment 51259 [details] > added missing error check on fclose in gcc/gcov-io.c > > Well, not all errors are detected. There is a missing test in gcc/gcov-io.c > for fclose (which does a write system call to flush the buffers): > > --- a/gcc/gcov-io.c > +++ b/gcc/gcov-io.c > @@ -199,7 +199,8 @@ gcov_close (void) > { > if (gcov_var.file) > { > - fclose (gcov_var.file); > + if (fclose (gcov_var.file)) > + gcov_var.error = 1; > gcov_var.file = 0; > } > gcov_var.mode = 0; > > (also in attachment). I've tested this patch, and it solves my problem: Great job! I was aware of the fclose, but didn't realize it fails during flushing. May I please install the patch on your behalf?
(In reply to Martin Liška from comment #7) > May I please install the patch on your behalf? Yes. Thanks.
The master branch has been updated by Martin Liska <marxin@gcc.gnu.org>: https://gcc.gnu.org/g:929f2cf4105ccf12d0684c6d5838f58f0ee5e7c7 commit r12-2736-g929f2cf4105ccf12d0684c6d5838f58f0ee5e7c7 Author: Vincent Lefèvre <vincent-gcc@vinc17.net> Date: Wed Aug 4 17:25:52 2021 +0200 gcov: check return code of a fclose gcc/ChangeLog: PR gcov-profile/101773 * gcov-io.c (gcov_close): Check return code of a fclose.
Thanks for your cooperation, fixed on master.