Hello, I've noticed a specific type of pipe() usage that works in released R, but not in r-devel. In 4.3.2 on macOS, I can write to a connection returned by pipe(), i.e. "hello, world" prints here:> R.version.string[1] "R version 4.3.2 (2023-10-31)"> con <- pipe("cat") > writeLines("hello, world", con)hello, world But in r-devel on macOS, this is silent no-op, i.e. "hello, world" does not print:> R.version.string[1] "R Under development (unstable) (2024-02-13 r85895)"> con <- pipe("cat") > writeLines("hello, world", con)My colleague Lionel Henry confirms he sees the same results on linux. This particular example with cat doesn't work on Windows, so I don't have any useful observations for that OS. You might say this is a weird example or use case. The actual usage where I discovered this is the way folks read/write the clipboard on macOS using pbcopy/pbpaste (and, in very similar ways, on linux using xsel or xclip). This is mentioned in the "Clipboard" section of the connections help topic. In 4.3.2 on macOS, I can successfully roundtrip with the clipboard:> pb_write <- pipe("pbcopy") > writeChar("hello clipboard!", pb_write, eos = NULL) > pb_read <- pipe("pbpaste") > readChar(pb_read, 16)[1] "hello clipboard!" In r-devel, it appears that the write operation silently does nothing:> pb_write <- pipe("pbcopy") > writeChar("hello clipboard!", pb_write, eos = NULL) > pb_read <- pipe("pbpaste") > readChar(pb_read, 16)character(0) If the clipboard is populated through other means, I can use readChar(pipe("pbpaste"), ...) to read the clipboard even in r-devel. So this seems to be specific to writing to the connection. Is this change in behaviour intentional and will it be present in the next release of R? FWIW, I did a crude search of the source of all CRAN packages and there are quite a few currently using pipe() for clipboard access on *nix. -- Jenny [[alternative HTML version deleted]]
? Wed, 14 Feb 2024 14:43:12 -0800 Jennifer Bryan <jenny.f.bryan at gmail.com> ?????:> But in r-devel on macOS, this is silent no-op, i.e. "hello, world" > does not print: > > > R.version.string > [1] "R Under development (unstable) (2024-02-13 r85895)" > > con <- pipe("cat") > > writeLines("hello, world", con)I can reproduce this on 64-bit Linux. I think that this boils down to problems with cleanup in R_pclose_pg [*]. The FILE* fp corresponding to the child process pipe is created using fdopen() in R_popen_pg(), but R_pclose_pg() only performs close() on the file descriptor returned by fileno(). The FILE* itself is leaked, and any buffered content waiting to be written out is lost. One of the last few lines in the strace output before the process terminates is the standard C library cleaning up the FILE* object and trying to flush the buffer: $ strace -f bin/R -q -s \ -e 'writeLines("hello", x <- pipe("cat")); close(x)' ...skip... write(5, "hello\n", 6) = -1 EBADF (Bad file descriptor) exit_group(0) = ? +++ exited with 0 +++ There is a comment saying "see timeout_wait for why not to use fclose", which I think references a different function, R_pclose_timeout():>> Do not use fclose, because on Solaris it sets errno to "Invalid >> seek" when the pipe is already closed (e.g. because of timeout). >> fclose would not return an error, but it would set errno and the >> non-zero errno would then be reported by R's "system" function.(There are no comments about fclose() in timeout_wait() itself.) Is there a way to work around the errno problem without letting the FILE* leak? -- Best regards, Ivan [*] Introduced in https://bugs.r-project.org/show_bug.cgi?id=17764#c6 to run child processes in a separate process group, safe from interrupts aimed at R.
On 2/14/24 23:43, Jennifer Bryan wrote:> Hello, > > I've noticed a specific type of pipe() usage that works in released R, but > not in r-devel. > > In 4.3.2 on macOS, I can write to a connection returned by pipe(), i.e. > "hello, world" prints here: > >> R.version.string > [1] "R version 4.3.2 (2023-10-31)" >> con <- pipe("cat") >> writeLines("hello, world", con) > hello, world > > But in r-devel on macOS, this is silent no-op, i.e. "hello, world" does not > print: > >> R.version.string > [1] "R Under development (unstable) (2024-02-13 r85895)" >> con <- pipe("cat") >> writeLines("hello, world", con) > My colleague Lionel Henry confirms he sees the same results on linux. > This particular example with cat doesn't work on Windows, so I don't have > any useful observations for that OS. > > You might say this is a weird example or use case. The actual usage where I > discovered this is the way folks read/write the clipboard on macOS using > pbcopy/pbpaste (and, in very similar ways, on linux using xsel or xclip). > This is mentioned in the "Clipboard" section of the connections help topic. > > In 4.3.2 on macOS, I can successfully roundtrip with the clipboard: > >> pb_write <- pipe("pbcopy") >> writeChar("hello clipboard!", pb_write, eos = NULL) >> pb_read <- pipe("pbpaste") >> readChar(pb_read, 16) > [1] "hello clipboard!" > > In r-devel, it appears that the write operation silently does nothing: > >> pb_write <- pipe("pbcopy") >> writeChar("hello clipboard!", pb_write, eos = NULL) >> pb_read <- pipe("pbpaste") >> readChar(pb_read, 16) > character(0) > > If the clipboard is populated through other means, I can > use readChar(pipe("pbpaste"), ...) to read the clipboard even in r-devel. > So this seems to be specific to writing to the connection. > > Is this change in behaviour intentional and will it be present in the next > release of R? FWIW, I did a crude search of the source of all CRAN packages > and there are quite a few currently using pipe() for clipboard access on > *nix.This should be fixed now in R-devel. Thanks for the report and thanks to Ivan for the debugging. It would be great if you could test on your end with different examples and report any other issues. Thanks Tomas> > -- Jenny > > [[alternative HTML version deleted]] > > ______________________________________________ > R-devel at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel