Re: EDQUOT lurks in most apps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





On Wed, 11 Dec 2024 at 11:28, John Reiser <jreiser@xxxxxxxxxxxx> wrote:
There's a bug in this program.  Can you spot it?
=====
#include <stdio.h>

int
main(int argc, char *argv[])
{
     printf("Hello, world!\n");
     return 0;
}
=====

The bug is that EDQUOT (Disk Quota exceeded:
/usr/include/asm-generic/errno.h) is not detected.  If a shell
re-directs stdout into a file,
then the data might never be captured, and the problem would go
undetected until another program tries to read the file,
but does not find the expected data.

It is a very common programming error to omit the call to close() of an
output file, *AND/OR* not to check the return value of close().
["What could possibly go wrong?"  Answer: EDQUOT or ENOSPC.]
Upon exit(), then the Linux kernel implicitly closes all open file
descriptors, but *IGNORES ALL ERRORS* in doing so. It's even documented
on the manpage:  "Failing to check the return value when closing a file
may lead to silent loss of data.  This can especially be observed with
NFS and with disk quota" [or when the output goes into a VM container.]

The app should call close() and check the return value.  Before calling
close(), then a paranoid programmer will call fsync() (and check for
errors) in order to increase the reliability and integrity of data.


I have seen this listed as NOT A BUG even with realtime programmers because the application can be run in all kinds of ways which could induce failures that are 'environment' versus 'application'. I expect it depends on the exact environment but what is the correct code? Something like the following?

===

#include <stdio.h>
#include <stdlib.h>

// This would be better with subroutines but this is supposed to be
// hello world.
int main(int argc, char *argv[]){
    int err=0;
    err=printf("Hello, world!\n");
    if (err < 0){ // we got an error somewhere
        err=fclose(stdout);
        if (err != 0){ // we got a bigger error
            return err;
        }
        err=fclose(stderr);
        if (err != 0){ // we got a bigger error
            return err;
        }
        return 1;
    } else {
        err=fclose(stdout);
        if (err != 0){ // we got a bigger error
            return err;
        }
        err=fclose(stderr);
        if (err != 0){ // we got a bigger error
            return err;
        }
        return 0;
    }
}

===


--
Stephen Smoogen, Red Hat Automotive
Let us be kind to one another, for most of us are fighting a hard battle. -- Ian MacClaren
-- 
_______________________________________________
devel mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxx
To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxx
Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: https://lists.fedoraproject.org/archives/list/devel@xxxxxxxxxxxxxxxxxxxxxxx
Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Fedora Announce]     [Fedora Users]     [Fedora Kernel]     [Fedora Testing]     [Fedora Formulas]     [Fedora PHP Devel]     [Kernel Development]     [Fedora Legacy]     [Fedora Maintainers]     [Fedora Desktop]     [PAM]     [Red Hat Development]     [Gimp]     [Yosemite News]

  Powered by Linux