[libvirt] mingw64 + gnulib time.h / pthread.h / gmtime_r incompatibility

Daniel P. Berrange berrange at redhat.com
Wed Jan 22 16:27:43 UTC 2014

I'm attempting to make libvirt capable of building with mingw64 toolchain's
pthread.h, instead of directly using Windows thread primitives.

As a quick hack I just changed libvirt logic to force use of pthreads,
since configure is already doing the neccessary pthread.h probes for us
even on win32 eg

diff --git a/src/util/virthread.c b/src/util/virthread.c
index dd1768e..8849d7d 100644
--- a/src/util/virthread.c
+++ b/src/util/virthread.c
@@ -25,7 +25,7 @@
 /* On mingw, we prefer native threading over the sometimes-broken
  * pthreads-win32 library wrapper.  */
-#ifdef WIN32
+#ifdef WINx32
 # include "virthreadwin32.c"
 # include "virthreadpthread.c"
diff --git a/src/util/virthread.h b/src/util/virthread.h
index 84d3bdc..649285e 100644
--- a/src/util/virthread.h
+++ b/src/util/virthread.h
@@ -111,7 +111,7 @@ int virThreadLocalInit(virThreadLocalPtr l,
 void *virThreadLocalGet(virThreadLocalPtr l);
 int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK;
-# ifdef WIN32
+# ifdef WINx32
 #  include "virthreadwin32.h"
 #  include "virthreadpthread.h"

When attempting to build though I see failures

  CC       util/libvirt_util_la-virerror.lo
In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/sys/time.h:10:0,
                 from ../gnulib/lib/sys/time.h:39,
                 from ../gnulib/lib/sys/select.h:117,
                 from util/virutil.h:31,
                 from util/virerror.c:35:
../gnulib/lib/time.h:468:21: error: expected identifier or '(' before '{' token
 _GL_FUNCDECL_SYS (localtime_r, struct tm *, (time_t const *restrict __timer,
In file included from /usr/i686-w64-mingw32/sys-root/mingw/include/sys/time.h:10:0,
                 from ../gnulib/lib/sys/time.h:39,
                 from ../gnulib/lib/sys/select.h:117,
                 from util/virutil.h:31,
                 from util/virerror.c:35:
../gnulib/lib/time.h:490:21: error: expected identifier or '(' before '{' token
 _GL_FUNCDECL_SYS (gmtime_r, struct tm *, (time_t const *restrict __timer,

The problem appears to be that mingw64's pthread.h has the following

/* Recursive API emulation.  */
#undef localtime_r
#define localtime_r(_Time, _Tm) ({ struct tm *___tmp_tm;                \
                                                pthread_testcancel();   \
                                                ___tmp_tm = localtime((_Time));\
                                                if (___tmp_tm) {        \
                                                  *(_Tm) = *___tmp_tm;  \
                                                  ___tmp_tm = (_Tm);    \
                                                }                       \
                                                ___tmp_tm;      })

#undef gmtime_r
#define gmtime_r(_Time,_Tm)     ({ struct tm *___tmp_tm;                \
                                                pthread_testcancel();   \
                                                ___tmp_tm = gmtime((_Time)); \
                                                if (___tmp_tm) {        \
                                                  *(_Tm) = *___tmp_tm;  \
                                                  ___tmp_tm = (_Tm);    \
                                                }                       \
                                                ___tmp_tm;      })

which clashes with the gnulib provided declarations for gmtime_r/localtime_r

gnulib appears to be trying to workaround this problem already - the
generated gnulib/lib/time.h file shows this though, which indicates
its workaround hasn't been activated by 'configure':

/* Some systems don't define struct timespec (e.g., AIX 4.1, Ultrix 4.3).
   Or they define it with the wrong member names or define it in <sys/time.h>
   (e.g., FreeBSD circa 1997).  Stock Mingw does not define it, but the
   pthreads-win32 library defines it in <pthread.h>.  */
# if ! 1
#  if 0
#   include <sys/time.h>
#  elif 0
#   include <pthread.h>
/* The pthreads-win32 <pthread.h> also defines a couple of broken macros.  */
#   undef asctime_r
#   undef ctime_r
#   undef gmtime_r
#   undef localtime_r
#   undef rand_r
#   undef strtok_r
#  else

ie I would have expected that 'elif' to be 1 instead of 0.

It seems the logic in gnulib/m4/time_h.m4 is incorrect. The configure
check shows

  checking for struct timespec in <time.h>... yes

and so  time_h.m4 never gets as far as trying to detect the broken
pthreads.h - its hidden in an unreachable else block.

|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

More information about the libvir-list mailing list