Skip to content

Conversation

@GitMensch
Copy link
Collaborator

@GitMensch GitMensch commented Aug 13, 2025

note: while _POSIX_TIMERS may be "indirectly" defined by including time.h on some systems, they come from unistd.h.

tested to work on Debian and MSYS2 (gcc + clang)

fixes #345 (C part)

to be checked:
Is there an environment where this does not work (it seems that on non-released mingwrt we do have the feature with clock_gettime since Dec 2017 but no posix-feature-macros at all; not sure if this is something to care for)?

Should we apply something similar to other places? See https://linux.die.net/man/7/posixoptions.

note: while _POSIX_TIMERS is "directly" defined by including time.h on some systems, it may only be done if the internal macros are defined, which is commonly done by including unistd.h, so that is done before

tested to work on Debian and MSYS2 (gcc + clang)

fixes #345 (C part)
@GitMensch GitMensch requested a review from Bill-Gray August 13, 2025 07:23
@GitMensch GitMensch marked this pull request as draft August 13, 2025 07:24
@GitMensch GitMensch changed the title use POSIX feature macro do check for clock_gettime use POSIX feature macro to check for clock_gettime Aug 13, 2025
@GitMensch GitMensch marked this pull request as ready for review September 15, 2025 06:38
@GitMensch
Copy link
Collaborator Author

ping @Bill-Gray for review/merge

@Bill-Gray
Copy link
Owner

I just tried building WinGUI and WinCon, cross-compiling on my Linux box. For both, I got :

x86_64-w64-mingw32-gcc -Wl,--out-implib,pdcurses.a -static-libgcc -shared -o pdcurses.dll addch.o addchstr.o addstr.o attr.o beep.o bkgd.o border.o clear.o color.o debug.o delch.o deleteln.o getch.o getstr.o getyx.o inch.o inchstr.o initscr.o inopts.o insch.o insstr.o instr.o kernel.o keyname.o mouse.o move.o outopts.o overlay.o pad.o panel.o printw.o refresh.o scanw.o scr_dump.o scroll.o slk.o termattr.o terminfo.o touch.o util.o window.o pdcclip.o pdcdisp.o pdcgetsc.o pdckbd.o pdcscrn.o pdcsetsc.o pdcutil.o -lgdi32 -lcomdlg32 -lwinmm
/usr/bin/x86_64-w64-mingw32-ld: getch.o:getch.c:(.text+0x61e): undefined reference to `clock_gettime'
/usr/bin/x86_64-w64-mingw32-ld: getch.o:getch.c:(.text+0xe8c): undefined reference to `clock_gettime'
collect2: error: ld returned 1 exit status
make: *** [Makefile:155: pdcurses.dll] Error 1

So... compiled without trouble, but couldn't link. Presumably, there's something a little more subtle about when the various timing functions are available to us... any ideas?

I also built with Digital Mars and OpenWATCOM 1.9, each for DOS and WinCon, and it all worked and the resulting testcurs.exe files worked in DOSBox and the Wine console, respectively.

I also compiled everything with both of those compilers for OS/2. I mention this just for completeness, since I don't actually have an OS/2-capable machine on which to test the results. I got build errors with DMC, but I've had those before (don't know why); it's not related to the current issue. With OpenWATCOM, everything compiled without warnings or errors.

So I think if we can figure out a fix for the above error message, we'd be good.

@GitMensch
Copy link
Collaborator Author

For clock_gettime we'd nee to add -lrt (for glibc only necessary before 2.17, see https://www.man7.org/linux/man-pages/man3/clock_gettime.3.html - but likely no problem to do so in any case), no?

Can you please test if adding it to the Makefile(s) works for your other build environments?

@Bill-Gray
Copy link
Owner

Sorry, should have just given this a go right away... especially since the only change required on my machine was adding -lrt to Makefile.

Unfortunately, it didn't work, because (with my MinGW version 9.3-win32 20200320)
there's no rt library available. I see the original comment in the code said that

   /* only newer MinGW environments have clock_gettime and
      those have CLOCK_REALTIME as a macro */

So the question becomes : how do we reliably determine that a given version of MinGW actually has clock_gettime()? I'm assuming the original method (if CLOCK_REALTIME is #defined, we've got it) failed on your system. Your new method (if _POSIX_TIMERS is #defined and is positive) fails on mine.

It appears that there are portability problems with clock_gettime(); in particular,

This function is missing on some platforms: Mac OS X 10.11, Minix 3.1.8, mingw, MSVC 14.
This function leaves the upper 32 bits of the tv_sec field of the result uninitialized on some platforms: mingw in 32-bit mode.

This is a little puzzling to me, since it seems to say that the function is missing for MinGW, and it also doesn't work. Seems to me it should be one or the other. (Maybe they mean "missing on old MinGW and broken on newer MinGW"?)

The implication is that we need to initialize tv_sec ourselves before calling clock_gettime(), presumably to zero. That does introduce a Y2038 problem, of course.

The following patch, which simply says "don't use clock_gettime() on MinGW because we can't really tell if it'll be available", compiles and Works On My Machine™ :

diff --git a/pdcurses/getch.c b/pdcurses/getch.c
index 78d0dbbb..a19ac8e5 100644
--- a/pdcurses/getch.c
+++ b/pdcurses/getch.c
@@ -419,9 +419,8 @@ use clock_gettime() or gettimeofday() when available. */
 #endif
 
 #if defined( _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L) \
-     && (!defined( __MINGW32__) || defined( CLOCK_REALTIME))
-   /* only newer MinGW environments have clock_gettime and
-      those have CLOCK_REALTIME as a macro */
+                    && !defined( __MINGW32__)
+   /* only newer MinGW environments have clock_gettime */
    #define HAVE_CLOCK_GETTIME
 #elif defined( _DEFAULT_SOURCE) || defined( _BSD_SOURCE) \
      || defined( __FreeBSD__) || defined( __MINGW32__)

However (as it says just below that patch) "POSIX.1-2008 marks gettimeofday() as obsolete, recommending the use of clock_gettime() instead." I would think that on some suitably modern version of MinGW, the above might get us a deprecation warning.

So ideally, we'd find out with which version of MinGW the rt library (and the clock_gettime() function) were added, and would choose the timing function based off that. (Well, that's not true. Ideally, the MinGW constants wouldn't make us think clock_gettime() was available, when it isn't.)

@GitMensch
Copy link
Collaborator Author

Your new method (if _POSIX_TIMERS is #defined and is positive) fails on mine.

That's... strange. can you run what we effectively do with this PR please?

echo | gcc -dM -E --include unistd.h --include time.h --include sys/time.h - | grep -i "time\|clock"

?

Note: we still may have to add -lrt for non !WIN32 compilations to the Makefile though.

@Bill-Gray
Copy link
Owner

Figured it out... clock_gettime() is defined in pthread_time.h. That caused me to try -lpthread, which worked. Yes, it's supposed to be in the rt library. But it appears it's not.

So I am reasonably confident that your fix will work (works here, anyway). I am just sufficiently worried by these problems that I'd rather hold off on having it in a release version, though.

The other possibility (maybe safer) is to say that we only use clock_gettime() if the glibc version is 2.17 or later (that is to say, if we can use it without having to add in rt or pthread).

I'm going to go ahead with the release "as is" (basically just change version constants and, in HISTORY.md, replace "Current PDCursesMod - 2026 January 06" with "PDCursesMod 4.5.4 - 2026 January 07"). That may lead to 4.5.5 coming out rather shortly afterward, after we've got a change we both like and it passes the GitHub Actions and Appveyor tests.

@GitMensch
Copy link
Collaborator Author

Sounds good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MinGW: getch.c does not build, no option to work around via Makefile

2 participants