fclose: close stream even if there is an error flushing buffered data.

This can happen, e.g., if there is an IO error or if there is insufficient free disk space to flush the data. In this case, fclose should return -1 to report an error, but it should still effectively close the stream and deallocate the buffer for it. (This behavior is explicitly specified in the C99 and later standards.)

Previously, ORCA/C effectively left the stream open in these cases. As a result, the buffer was not deallocated. More importantly, this could cause the program to hang at exit, because the stream would never be removed from the list of open files.

Here is an example program that demonstrates the problem:

/*
 * Run this on a volume with less than 1MB of free space, e.g. a floppy.
 * The fclose return value should be -1 (EOF), indicating an error, but
 * the two RealFreeMem values should be close to each other (indicating
 * that the buffer was freed), and the program should not hang on exit.
 */

#include <stdio.h>
#include <stddef.h>
#include <memory.h>

#define BUFFER_SIZE 1000000

int main(void) {
        size_t i;
        int ret;

        printf("At start, RealFreeMem = %lu\n", RealFreeMem());

        FILE *f = fopen("testfile", "wb");
        if (!f)
                return 0;

        setvbuf(f, NULL, _IOFBF, BUFFER_SIZE);

        for (i = 0; i < BUFFER_SIZE; i++) {
                putc('x', f);
        }

        ret = fclose(f);
        printf("fclose return value = %d\n", ret);

        printf("At end, RealFreeMem = %lu (should be close to start value)\n",
                RealFreeMem());
}
This commit is contained in:
Stephen Heumann 2024-02-19 22:30:15 -06:00
parent 9d42552756
commit 16c7952648
1 changed files with 7 additions and 7 deletions

View File

@ -83,16 +83,13 @@ stdfile equ 7 is this a standard file?
phk phk
plb plb
lda #EOF assume we will get an error
sta err
ph4 <stream verify that stream exists ph4 <stream verify that stream exists
jsl ~VerifyStream jsl ~VerifyStream
jcs rts jcs rts_err
ph4 <stream do any pending I/O ph4 <stream do any pending I/O
jsl fflush jsl fflush
tax sta err initialize err to fflush result
jne rts
stz stdfile not a standard file stz stdfile not a standard file
lda stream+2 bypass file disposal if the file is lda stream+2 bypass file disposal if the file is
@ -113,7 +110,7 @@ cl0 lla p,stderr+4 find the file record that points to this
cl1 lda [p],Y cl1 lda [p],Y
tax tax
ora [p] ora [p]
jeq rts jeq rts_err
lda [p] lda [p]
cmp stream cmp stream
bne cl2 bne cl2
@ -188,7 +185,10 @@ cl6 lda [p],Y
dey dey
cpy #2 cpy #2
bne cl6 bne cl6
cl7 stz err no error found cl7 bra rts no error found
rts_err lda #EOF
sta err
rts plb rts plb
creturn 2:err creturn 2:err