On Sun, Sep 22, 2002 at 04:24:31AM +0900, Jos Backus wrote:
> On Sun, Sep 22, 2002 at 01:06:51AM +0900, nobu.nokada / softhome.net wrote:
> > Have you asked Sun about this issue?
>  
> Not yet, first I want to make sure that this is indeed the issue. I will try
> to instrument io_write() to figure out what is going on (e.g. write the data
> to stderr -> a file when the fwrite() sees EINTR and compare n and the data
> with the actual output). I will report back what I find.

It turns out that this is a Solaris issue afaIct. See

    http://www.catnook.com/programs/fwrite-bug.c

for a short program demonstrating the issue.  We intend to file a bugreport
with Sun shortly.

Meanwhile I intend to use the following patch (against today's HEAD).  An
earlier version saved the original mask, blocked SIGVTALRM, called fwrite(),
then restored the original mask, but this seems to be safe enough.  Can
anybody see anything wrong with it?

Index: io.c
===================================================================
RCS file: /src/ruby/io.c,v
retrieving revision 1.167
diff -u -r1.167 io.c
--- io.c	29 Oct 2002 21:35:28 -0000	1.167
+++ io.c	6 Nov 2002 04:36:52 -0000
@@ -384,7 +384,21 @@
 	}
     } while (--n > 0);
 #else
-    while (ptr += (r = fwrite(ptr, 1, n, f)), (n -= r) > 0) {
+#if defined(__sun__) && defined(__svr4__)
+    /* Prevent the fwrite() from being interrupted by a VTALRM signal */
+    sigset_t set;
+    sigemptyset(&set);
+    sigaddset(&set, SIGVTALRM);
+#endif
+    for (;;) {
+#if defined(__sun__) && defined(__svr4__)
+	sigprocmask(SIG_BLOCK, &set, 0);
+#endif
+	ptr += (r = fwrite(ptr, 1, n, f));
+#if defined(__sun__) && defined(__svr4__)
+	sigprocmask(SIG_UNBLOCK, &set, 0);
+#endif
+	if ((n -= r) <= 0) break;
 	if (ferror(f)) {
 	    if (rb_io_wait_writable(fileno(f))) {
 		clearerr(f);

Thanks,
-- 
Jos Backus                       _/  _/_/_/      Sunnyvale, CA
                                _/  _/   _/
                               _/  _/_/_/
                          _/  _/  _/    _/
jos at catnook.com        _/_/   _/_/_/          require 'std/disclaimer'