Skip to content

Rscript -e EXPR fails to launch if stdin is closed

7 messages · Henrik Bengtsson, Peter Dalgaard, Dirk Eddelbuettel

#
Rscript fails to launch if the standard input (stdin) is closed, e.g.

$ Rscript --vanilla -e 42 0<&-
Fatal error: creating temporary file for '-e' failed

This appear to only happen with `-e EXPR`, e.g. it works when doing:

$ echo "42" > script.R
$ Rscript --vanilla script.R 0<&-
[1] 42

and:

$ R --vanilla 0<&-
R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
Copyright (C) 2022 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
...
TROUBLESHOOTING:

$ strace Rscript --vanilla -e 42 0<&-
execve("/home/hb/shared/software/CBI/R-4.2.1-gcc9/bin/Rscript",
["Rscript", "--vanilla", "-e", "42"], 0x7fff9f476418 /* 147 vars */) =
0
brk(NULL)                               = 0x5625ca9e6000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fff23b4d260) = -1 EINVAL (Invalid argument)
...
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0), ...}) = 0
write(1, "Fatal error: creating temporary "..., 53Fatal error:
creating temporary file for '-e' failed
) = 53
exit_group(2)                           = ?
+++ exited with 2 +++

which points to src/unix/system.c:

ifd = mkstemp(ifile);
if (ifd > 0)
    ifp = fdopen(ifd, "w+");
if(!ifp) R_Suicide(_("creating temporary file for '-e' failed"));


One rationale for having closed standard files (including stdin) is to
avoid leaking file descriptors, cf.
https://wiki.sei.cmu.edu/confluence/display/c/FIO22-C.+Close+files+before+spawning+processes
and https://danwalsh.livejournal.com/53603.html.  The background for
reporting on this was that `system()` fails to work in processx
spawned processes, which closes the standard files by default in
processx (<= 3.7.0).

Best,

Henrik
#
He! 

Yes, that looks like a blunder.

mkstemp() returns -1 on failure, not 0, so the test on ifd (and I suppose also the one on ifp) is wrong. And of course, once you close file descriptor 0, mkstemp() chooses the 1st available fd, i.e. 0, for its return value.

-pd

  
    
#
It seems to work simply to do  "if (ifd >= 0)..." (the ifp test is fine since ifp is FILE* and initialized to NULL). Will commit (to r-devel for now).

-pd

  
    
#
Thank you Peter for the quick fix.  Will this make it into R-patched
to become R 4.2.2 soon?

I can confirm that the fix resolved also the original problem report
involving launching a parallel PSOCK cluster from within a 'processx'
background process
(https://stackoverflow.com/questions/73962109/why-are-the-workers-failing-to-connect-when-calling-makepsockcluster-from-an-e/73991833#73991833
and https://github.com/r-lib/callr/issues/236)


/Henrik
On Mon, Oct 10, 2022 at 5:54 AM peter dalgaard <pdalgd at gmail.com> wrote:
#
There's still 2 weeks till code freeze for 4.2.2, and porting the fix would be trivial. As long as there is no risk that someone will get the bright idea of changing a critical package to depend on R >= 4.2.2...

- pd

  
    
2 days later
#
On 10 October 2022 at 09:34, Henrik Bengtsson wrote:
| Thank you Peter for the quick fix.  Will this make it into R-patched
| to become R 4.2.2 soon?

I checked when you posted this and didn't reply -- but this is also not an
issue for littler so if you need alternative there is one

  $ Rscript --vanilla -e 42 0<&- 
  Fatal error: creating temporary file for '-e' failed
  $
  $ r -p -e 42 0<&-      # -p to force print
  [1] 42
  $ 

Dirk
#
Done... -pd