Hello fdclose

Mariusz Zaborski oshogbo at FreeBSD.org
Tue Mar 25 22:25:29 UTC 2014


> Does this patch allow perl to stop writing to FILE._file? As pointed out
> in
> http://lists.freebsd.org/pipermail/freebsd-current/2013-January/039024.html
> perlio.c in the perl source contains a function
> PerlIOStdio_invalidate_fileno() that should modify a FILE such that
> fclose() does not close the file descriptor but still frees all memory
> (Perl has already called fflush()). Although using fdclose() could solve
> this without touching the internals of FILE, this will make perlio.c
> uglier with even more #ifdefs.
Yes it should help. I start some work on it but i have some troubles
with perl (I'm not perl hacker :(), so I will try to prepare some
patch for it in the nearest feature. There are some other places also
where we could use it.

>> [snip]
>> --- //depot/user/oshogbo/capsicum/lib/libc/stdio/Symbol.map   2013-06-28 08:51:28.000000000 0000
>> +++ /home/oshogbo/p4/capsicum/lib/libc/stdio/Symbol.map       2013-06-28 08:51:28.000000000 0000
>> @@ -156,6 +156,7 @@
>>       putwc_l;
>>       putwchar_l;
>>       fmemopen;
>> +     fdclose;
>>       open_memstream;
>>       open_wmemstream;
>>  };
>
> This should be in the FBSD_1.4 namespace (which does not exist yet).

Oh - thx, so this will be good now?

@@ -160,6 +160,10 @@
  open_wmemstream;
 };

+FBSD_1.4 {
+ fdclose;
+};
+

>> [snip]
>> --- //depot/user/oshogbo/capsicum/lib/libc/stdio/fclose.c     2013-06-28 08:51:28.000000000 0000
>> +++ /home/oshogbo/p4/capsicum/lib/libc/stdio/fclose.c 2013-06-28 08:51:28.000000000 0000
>> [snip]
>> +int
>> +fdclose(FILE *fp)
>> +{
>> +     int fd, r, err;
>> +
>> +     if (fp->_flags == 0) {  /* not open! */
>> +             errno = EBADF;
>> +             return (EOF);
>> +     }
>> +
>> +     r = 0;
>> +     FLOCKFILE(fp);
>> +     fd = fp->_file;
>> +     if (fp->_close != __sclose) {
>> +             r = EOF;
>> +             errno = EOPNOTSUPP;
>> +     } else if (fd < 0) {
>> +             r = EOF;
>> +             errno = EBADF;
>> +     }
>> +     if (r == EOF) {
>> +             err = errno;
>> +             (void)cleanfile(fp, true);
>> +             errno = err;
>> +     } else {
>> +             r = cleanfile(fp, false);
>> +     }
>>       FUNLOCKFILE(fp);
>> +
>> +     return (r == 0 ? fd : r);
>
> If a file descriptor would be returned but cleanfile() returns an error
> (e.g. write error on flush), the file descriptor is not returned and not
> closed.
>
> I think that in cases where fdclose() would be used, it is essential
> that the file descriptor is never closed. This means that the API needs
> to be different so it can report a write error but still return a file
> descriptor. One way to do this is to return the file descriptor by
> reference. Another is to expect the application to call fileno() and not
> return the descriptor from the new function.
You have very good point. The first question is where function will
return error:
1* When there is different _close function from std (it will behave
like fclose with some errno)
2* When __sflush fails (and it will free structure)
3* When fd in structure is not correct (it will behave like fclose
with some errno)

I think those assumptions about when close fd are reasonable. When I
wrote this function I discouse this with Pawel, and we decided that if
_close function is different from std we should work same as fclose
function plus return errno about EOPNOTSUPP.

So in my opinion only second point is unwanted by us. So if __sflush
fails we could not return any err (I don't thing this is wanted
solution) or we could return error returned by __sflush and not free
structure. In my opinion last option will be the best one. What you
think Jilles?

In this moment I don't like idea of changing API of this function.

Cheers,
Mariusz


More information about the freebsd-arch mailing list