bug-gnulib
[Top][All Lists]
Advanced

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

Re: getting EBADF on MSVC


From: Bruno Haible
Subject: Re: getting EBADF on MSVC
Date: Sat, 24 Sep 2011 13:53:09 +0200
User-agent: KMail/1.13.6 (Linux/2.6.37.6-0.5-desktop; KDE/4.6.0; x86_64; ; )

Hi Paul,

> I briefly looked at the more recent changes you installed, and have
> some further comments and suggestions and a couple of patches.
> 
>   * Why two files, msvc-inval.h and msvc-nothrow.h?
>     Would it be simpler to have just one file?
>     Is it likely that a package would want one but not the other?
>     The "AC_DEFUN([gl_MSVC_NOTHROW], [AC_REQUIRE([gl_MSVC_INVAL])])"
>     suggests that the two msvc-* modules should be merged, or at
>     least that gl_MSVC_NOTHROW and m4/msvc-nothrow.m4 should be removed.

One of the reasons why 'libit' failed but gnulib succeeded is that it was
part of every 'libit's coding conventions that every feature should be
implemented in a single .c file and not more. This required manual work
when accommodating source code such as e.g. libintl. In other words,
the desire to minimize the number of files did not allow the code to be
structured in a good way.

If you are asking to minimize the number of source code files, this goes
against proper design and maintainability.

I chose to make 'msvc-inval' and 'msvc-nothrow' two different files because
they implement two different (but related) layers: 'msvc-inval' provides
the ability to catch invalid parameter notifications, whereas 'msvc-nothrow'
applies this ability to particular functions (currently only one, but maybe
more in the future).

Optimizing m4/msvc-nothrow.m4 is a needless micro-optimization. We have
hundreds of modules that have a part in lib/ and a part in m4/. It's part
of the coding style for gnulib to have a .m4 file, otherwise there is the
tendency to put it into the module description. We have even entirely no-op
.m4 files, like m4/i-ring.m4 or m4/xgetcwd.m4.

It is more important to have the room for new code to be added in the proper
places, than to reduce the number of files.

>   * Why is the body of msvc-inval.c protected inside
>     HAVE_MSVC_INVALID_PARAMETER_HANDLER?  Surely that file is compiled
>     only when the macro is true.  There's a similar issue for
>     msvc-nothrow.c.

Yes, this #if is technically redundant, because the 'if test ...'
in the module description avoids a completely empty compilation unit
anyway. I put in the #if so that the structure of the .c file is similar
to the structure of the .h file.

>   * Why does dup2.c need to use 'inline'?  When a static function is
>     used in only one place, 'inline' is typically verbosity that's not
>     needed: a compiler that's optimizing will inline anyway, and if
>     we're not optimizing, then typically we won't want the inlining
>     (for debugging purposes).  A similar comment applies to other
>     *_nothrow functions.

Do you know the optimizing behaviour of MSVC, or are you making assumptions?
What I found out is that with MSVC 9, inlining is triggered by the
"global optimizations" switch, and for small static functions, it does it
also without the programmer specifying 'inline'. What I also know from MSVC
4/5/6, is that this "global optimizations" switch leads to compiler bugs.
I don't know if there is another (reliable) optimization switch for MSVC 9
that would enable inlining.

So, it may be that you have a point here and that the 'inline's are
unnecessary. But I don't have enough knowledge about MSVC compilers to
evaluate that.

>   * dup2.c can benefit from more reorganization to make it shorter and
>     easier to follow (especially for us non-Windows guys).  The basic
>     idea is to put the Windows-only stuff into a separate section,
>     easily delimited via an #if.  I took a stab at doing that (see
>     below), and the result is shorter (and to my eyes) clearer

It is clearer, yes. But your patch has three problems:

* It contains the code

  if (fd == desired_fd)
    return fcntl (fd, F_GETFL) == -1 ? -1 : fd;

  unprotected by #ifs, which will lead to compilation failure on native
  Windows platforms. They don't have fcntl() nor F_GETFL. gnulib defines
  fcntl() on these platforms, but the 'dup2' module does not depend on
  the 'fcntl' module.

* Cygwin is completely mishandled.

  Fact #1: On Cygwin, i.e. when creating Cygwin executables on Cygwin,
  (defined _WIN32 || defined __WIN32__) may be true or may be false;
  it depends on the compilation options (-mwin32 vs. -mno-win32). But
  regardless of these options, the program will be using the libc API from
  cygwin.dll, not msvcrt.dll.

  Fact #2: Cygwin programs should normally *not* use <windows.h> and the
  Win32 API. This is explicit policy (see
  <http://www.cygwin.org/ml/cygwin/2011-09/msg00065.html>). It also
  reflects reality better: For a C programmer, Cygwin feels 90% like POSIX
  and 10% like Windows.

  As a consequence, never write

    #if defined _WIN32 || defined __WIN32__

  Always write

    #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__

  if you want to treat Cygwin like POSIX (which is the common case).
  Or

    #if (defined _WIN32 || defined __WIN32__) || defined __CYGWIN__

  if you want to treat Cygwin like native Windows (which is pretty rare).

* It adds a wrong comment:

   /* Cygwin 1.5.x dup2 (1, 1) returns 0.  */
   if (result == 0)
     result = desired_fd;

  Compare the code with doc/posix-functions/dup2.texi, you will notice that
  these two lines are needed for mingw and MSVC platforms, not for Cygwin.

> I haven't tested the new dup2.c under Windows

If you want, I can provide you ssh access to a Windows machine with Cygwin and
mingw installed and ready to use.

I have tested this patch on Cygwin and mingw.


2011-09-24  Bruno Haible  <address@hidden>

        dup2: Fix last commit.
        * lib/dup2.c: Restore comments. Treat Cygwin like Unix.
        (rpl_dup2): Disable fcntl workaround on native Windows.

--- lib/dup2.c.orig     Sat Sep 24 13:50:50 2011
+++ lib/dup2.c  Sat Sep 24 13:43:00 2011
@@ -29,20 +29,22 @@
 
 # undef dup2
 
-# if defined _WIN32 || defined __WIN32__
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* Get declarations of the Win32 API functions.  */
+#  define WIN32_LEAN_AND_MEAN
+#  include <windows.h>
+
 #  include "msvc-inval.h"
-#  ifndef __CYGWIN__
-#   define WIN32_LEAN_AND_MEAN
-#   include <windows.h>
-#   include "msvc-nothrow.h"
-#  endif
+
+/* Get _get_osfhandle.  */
+#  include "msvc-nothrow.h"
 
 static inline int
 ms_windows_dup2 (int fd, int desired_fd)
 {
   int result;
 
-#  ifndef __CYGWIN__
   /* If fd is closed, mingw hangs on dup2 (fd, fd).  If fd is open,
      dup2 (fd, fd) returns 0, but all further attempts to use fd in
      future dup2 calls will hang.  */
@@ -55,7 +57,6 @@
         }
       return fd;
     }
-#  endif
 
   /* Wine 1.0.1 return 0 when desired_fd is negative but not -1:
      http://bugs.winehq.org/show_bug.cgi?id=21289 */
@@ -76,13 +77,14 @@
     }
   DONE_MSVC_INVAL;
 
-  /* Cygwin 1.5.x dup2 (1, 1) returns 0.  */
   if (result == 0)
     result = desired_fd;
 
   return result;
 }
+
 #  define dup2 ms_windows_dup2
+
 # endif
 
 int
@@ -90,10 +92,13 @@
 {
   int result;
 
+# if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)
   /* On Linux kernels 2.6.26-2.6.29, dup2 (fd, fd) returns -EBADF.
+     On Cygwin 1.5.x, dup2 (1, 1) returns 0.
      On Haiku, dup2 (fd, fd) mistakenly clears FD_CLOEXEC.  */
   if (fd == desired_fd)
     return fcntl (fd, F_GETFL) == -1 ? -1 : fd;
+# endif
 
   result = dup2 (fd, desired_fd);
 

-- 
In memoriam Sara Harpman 
<http://www.genealogieonline.nl/en/stamboom-harpman/I399.php>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]