changeset 15763:05e615abe919

read: Support for MSVC 9. * lib/unistd.in.h (read): Replace also when GNULIB_UNISTD_H_NONBLOCKING is not 1. * lib/read.c (read_nothrow): New function. (rpl_read): Define also when GNULIB_NONBLOCKING is not 1. Use read_nothrow. * m4/read.m4 (gl_FUNC_READ): Replace read if the platform has an invalid parameter handler. (gl_PREREQ_READ): New macro. * modules/read (Depends-on): Add msvc-inval. (configure.ac): Invoke gl_PREREQ_READ. * doc/posix-functions/read.texi: Mention the problem on MSVC.
author Bruno Haible <bruno@clisp.org>
date Sat, 24 Sep 2011 04:07:12 +0200
parents 6c4cf50b8b27
children f19a42ecd35b
files ChangeLog doc/posix-functions/read.texi lib/read.c lib/unistd.in.h m4/read.m4 modules/read
diffstat 6 files changed, 67 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2011-09-23  Bruno Haible  <bruno@clisp.org>
+
+	read: Support for MSVC 9.
+	* lib/unistd.in.h (read): Replace also when GNULIB_UNISTD_H_NONBLOCKING
+	is not 1.
+	* lib/read.c (read_nothrow): New function.
+	(rpl_read): Define also when GNULIB_NONBLOCKING is not 1. Use
+	read_nothrow.
+	* m4/read.m4 (gl_FUNC_READ): Replace read if the platform has an
+	invalid parameter handler.
+	(gl_PREREQ_READ): New macro.
+	* modules/read (Depends-on): Add msvc-inval.
+	(configure.ac): Invoke gl_PREREQ_READ.
+	* doc/posix-functions/read.texi: Mention the problem on MSVC.
+
 2011-09-23  Bruno Haible  <bruno@clisp.org>
 
 	close: Support for MSVC 9.
--- a/doc/posix-functions/read.texi
+++ b/doc/posix-functions/read.texi
@@ -9,6 +9,9 @@
 Portability problems fixed by Gnulib module @code{stdio}, together with module @code{nonblocking}:
 @itemize
 @item
+This function crashes when invoked with invalid arguments on some platforms:
+MSVC 9.
+@item
 When reading from a non-blocking pipe whose buffer is empty, this function
 fails with @code{errno} being set to @code{EINVAL} instead of @code{EAGAIN} on
 some platforms:
--- a/lib/read.c
+++ b/lib/read.c
@@ -20,25 +20,48 @@
 /* Specification.  */
 #include <unistd.h>
 
-/* Replace this function only if module 'nonblocking' is requested.  */
-#if GNULIB_NONBLOCKING
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+# include <errno.h>
+# include <io.h>
 
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
+
+# include "msvc-inval.h"
+# include "msvc-nothrow.h"
+
+# undef read
 
-#  include <errno.h>
-#  include <io.h>
+# if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static inline int
+read_nothrow (int fd, void *buf, size_t count)
+{
+  int result;
 
-#  define WIN32_LEAN_AND_MEAN  /* avoid including junk */
-#  include <windows.h>
+  TRY_MSVC_INVAL
+    {
+      result = read (fd, buf, count);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = -1;
+      errno = EBADF;
+    }
+  DONE_MSVC_INVAL;
 
-#  include "msvc-nothrow.h"
+  return result;
+}
+# else
+#  define read_nothrow read
+# endif
 
 ssize_t
 rpl_read (int fd, void *buf, size_t count)
-#undef read
 {
-  ssize_t ret = read (fd, buf, count);
+  ssize_t ret = read_nothrow (fd, buf, count);
 
+# if GNULIB_NONBLOCKING
   if (ret < 0
       && GetLastError () == ERROR_NO_DATA)
     {
@@ -54,8 +77,9 @@
             errno = EAGAIN;
         }
     }
+# endif
+
   return ret;
 }
 
-# endif
 #endif
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -1177,7 +1177,7 @@
 /* Read up to COUNT bytes from file descriptor FD into the buffer starting
    at BUF.  See the POSIX:2008 specification
    <http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html>.  */
-# if @REPLACE_READ@ && @GNULIB_UNISTD_H_NONBLOCKING@
+# if @REPLACE_READ@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
 #   undef read
 #   define read rpl_read
--- a/m4/read.m4
+++ b/m4/read.m4
@@ -1,4 +1,4 @@
-# read.m4 serial 2
+# read.m4 serial 3
 dnl Copyright (C) 2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -7,6 +7,10 @@
 AC_DEFUN([gl_FUNC_READ],
 [
   AC_REQUIRE([gl_UNISTD_H_DEFAULTS])
+  AC_REQUIRE([gl_MSVC_INVAL])
+  if test $HAVE_MSVC_INVALID_PARAMETER_HANDLER = 1; then
+    REPLACE_READ=1
+  fi
   dnl This ifdef is just an optimization, to avoid performing a configure
   dnl check whose result is not used. It does not make the test of
   dnl GNULIB_UNISTD_H_NONBLOCKING or GNULIB_NONBLOCKING redundant.
@@ -17,3 +21,9 @@
     fi
   ])
 ])
+
+# Prerequisites of lib/read.c.
+AC_DEFUN([gl_PREREQ_READ],
+[
+  AC_REQUIRE([AC_C_INLINE])
+])
--- a/modules/read
+++ b/modules/read
@@ -7,12 +7,14 @@
 
 Depends-on:
 unistd
+msvc-inval      [test $REPLACE_READ = 1]
 msvc-nothrow    [test $REPLACE_READ = 1]
 
 configure.ac:
 gl_FUNC_READ
 if test $REPLACE_READ = 1; then
   AC_LIBOBJ([read])
+  gl_PREREQ_READ
 fi
 gl_UNISTD_MODULE_INDICATOR([read])