lua-users home
lua-l archive

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


On Wed, Nov 25, 2015 at 12:54:25PM +0100, Mike Belopuhov wrote:
> Hi,
> 
> As many of you have most probably stumbled upon the problem with fdopen
> from the luaposix package on luajit and some of you have most probably
> solved it one way or another, I'd like to post my solution to this problem
> just for the purpose of archiving it and hopefully helping others.
> 
> But first a bit of a disclaimer: I do not consider myself an experienced
> Lua programmer and perhaps there are better solutions to this problem (-;
> 
> local stdio = require("posix.stdio")
> local unistd = require("posix.unistd")
> 
> function mikes_fdopen(fd)
> 	local fh, rv
> 
> 	fh = io.tmpfile()
> 	if (not fh) then
> 		return nil
> 	end
> 	fh:flush()
> 	rv = unistd.dup2(fd, stdio.fileno(fh))
> 	if (not rv) then
> 		fh:close()
> 		return nil
> 	end
> 	unistd.close(fd)
> 	return fh
> end
<snip>
> I'm open to any public criticism or a public discussion regarding this.
> Let me also say sorry in advance if this has already been presented
> before, that would just mean that my google-fu wasn't strong enough.

Several people have come up with similar solutions, but I don't think that
fact reflects poorly on your google-fu. ;)

Some comments:

1) POSIX fdopen takes a mode argument. You're only partially implementing
the interface by dup'ing the descriptor over the pre-existing descriptor.

2) In jailed environments there may be no /tmp or even any writable
directories at all.

The solution I arrived at in my own C-based Unix bindings module[1] is here

	https://github.com/wahern/lunix/blob/tag-20150923/src/unix.c#L3642

It attempts to open "." or "/dev/null" to get a blessed LuaJIT object using
io.open. Visibility or read permissions aren't guaranteed, but more likely
to work in a jailed environment. Then it replaces that FILE handle
completely with a newly fdopen'd handle rather than dup'ing over the
descriptor.

[1] lunix is thread-safe[2], provides common extensions not defined by POSIX
(with custom implementations if needed to make them "portable"), and is
regularly tested on many non-Linux platforms--AIX, OS X, Solaris, and
several different BSDs.

[2] At least as much as possible. The LuaJIT hack, for example, doesn't
permit properly emulating the "x" (O_CLOEXEC) flag to fdopen, which could
allow the temporary descriptor to be unintentionally inherited if another
thread calls forks at the same time. Although I just realized that LuaJIT
doesn't appear to check the contents of mode, so I should probably try to
pass it through. (And maybe also add a runtime check to see if the x flag is
supported by libc.)