Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 2 May 96 22:00:37 MDT
From:      sclawson@bottles.cs.utah.edu (steve clawson)
To:        sclawson@bottles.cs.utah.edu (sclawson)
Cc:        jmacd@CS.Berkeley.EDU, freebsd-hackers@freebsd.org
Subject:   Re: stdio problem
Message-ID:  <199605030400.WAA07893@bottles.cs.utah.edu>
In-Reply-To: <no.id>; from "sclawson" at May 2, 96 8:02 pm

next in thread | previous in thread | raw e-mail | index | archive | help
sclawson uttered:
> Josh MacDonald uttered:
> > Unfortunatly, I don't have control over this condition.  I am closing
> > the standard input and exec-ing GNU diff3.  Diff3 calls freopen. 
> > The comments in stdio/freopen.c say this should work.  It works everywhere
> > else.
> >
> > Your answers are not very helpful.
> 
>      Perhaps the answers weren't very explanatory, but they were
> correct.  Basically, your program is at the very least non-portable,
> and IMHO buggy.  Calling close(0) is _not_ the proper way to `close'
> stdin.  This just closes file descriptior 0, but dosen't do anything
> to close the stream stdin, which has user-level state.  You should use
> fclose() to close it if you really need to.  close() isn't even in
> ANSI C.  

     What I said is more or less reasonable in regards to the test
code that you sent, but isn't in regards to your original problem
(ie. having fd 0 closed and then execing diff3, which then does a
freopen on stdin).  After the exec, it dosen't matter if you used
close or fclose, any streams except the cannonical 3 are going to be
toast anyway.

     The real problem is in stdio/findfp.c:

FILE __sF[3] = {
        std(__SRD, STDIN_FILENO),               /* stdin */
        std(__SWR, STDOUT_FILENO),              /* stdout */
        std(__SWR|__SNBF, STDERR_FILENO)        /* stderr */
};

     since in stdio.h we have:

#define stdin   (&__sF[0])

     When the new process starts up, stdin looks reasonable to stdio,
but it's fd is invalid.  Which brings us back to the problem with
freopen, which only checks to see if anything is set in _flags. =(

     It seems to me that there's only really a problem in freopen if
we get back from the open the same fd that the stream supposedly was
using.  In that case we really don't want to be trying to close the
original stream, since we won't really be able to flush any buffers
back through the fd. =(

     At least for freopen, this seems to fix the problem:

*** freopen.c	Thu May  2 20:42:46 1996
--- /usr/arch/FreeBSD/current/lib/libc/stdio/freopen.c	Tue May 30 04:35:17 1995
***************
*** 109,115 ****
  	 * keep fp->_base: it may be the wrong size.  This loses the effect
  	 * of any setbuffer calls, but stdio has always done this before.
  	 */
! 	if (isopen && (fp->_file != f))
  		(void) (*fp->_close)(fp->_cookie);
  	if (fp->_flags & __SMBF)
  		free((char *)fp->_bf._base);
--- 109,115 ----
  	 * keep fp->_base: it may be the wrong size.  This loses the effect
  	 * of any setbuffer calls, but stdio has always done this before.
  	 */
! 	if (isopen)
  		(void) (*fp->_close)(fp->_cookie);
  	if (fp->_flags & __SMBF)
  		free((char *)fp->_bf._base);


     If fp->_close dosen't point to fclose things could screw up, but
if it does, the only thing that fclose does that freopen won't do is
call __sflush, which dosen't really matter if there's no fd to write
to anyway.  In fact, we probably don't want to try and flush out old
data to the fd that we just opened anyway.


steve

-- 
// stephen clawson				sclawson@cs.utah.edu
// university of utah			        




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199605030400.WAA07893>