Tk Source Code

View Ticket
Login
Ticket UUID: 3cb7c4ac72d4cdcc43b29adf0fa267e43bdebd5b
Title: tk inactive returns a negative value on Windows for long inactivity (32-bit overflow)
Type: Bug Version: 8.6, 9.0, 9.1
Submitter: serhiy.storchaka Created on: 2026-06-30 13:46:22
Subsystem: 63. Tk_Win Functions Assigned To: jan.nijtmans
Priority: 1 Zero Severity: Minor
Status: Closed Last Modified: 2026-09-17 07:52:58
Resolution: Fixed Closed By: oehhar
    Closed on: 2026-07-01 16:23:18
Description:

tk inactive returns a large negative number on Windows once inactivity reaches 2**31 ms (~24.8 days), instead of a non-negative millisecond count. In win/tkWinX.c, Tk_GetUserInactiveTime() returns the unsigned 32-bit GetTickCount() - li.dwTime as a long, which is 32-bit on Windows, so the high bit makes it negative. (On Unix/macOS long is 64-bit, so they are unaffected.)

Easy to hit on a non-interactive session (Windows service / session 0), where the inactivity is effectively the uptime; a CPython Windows buildbot caught it (https://github.com/python/cpython/issues/151881).

Since the API returns long, the fix clamps to 0x7fffffff rather than overflow.

Caveat: this only removes the spurious negatives. GetTickCount wraps every ~49.7 days, so beyond that the value wraps back toward zero regardless; that is inherent to the API and left as is.

User Comments: serhiy.storchaka added on 2026-09-17 07:52:58:

Thanks, I checked 8.6, 9.0 and main; all look good.

One nit on main: with Tk_GetUserInactiveTime() now returning long long, the LONG_MAX clamp in win/tkWinX.c is no longer needed and only truncates the 2**31..2**32-1 ms range (~24.8 to ~49.7 days). Branch [tk-inactive-no-clamp-2] removes it.

More than 32 bits is not possible on Windows: LASTINPUTINFO.dwTime is a DWORD, so inactivity is only known modulo ~49.7 days.


oehhar added on 2026-07-01 16:23:18:

Ja, thanks for the great work, we all appreciate.

Serhiy, may I ask you to double check and report here. You may comment on closed tickets.

Thanks, Harald


jan.nijtmans added on 2026-07-01 15:08:23:

Fixed [e38d6f17be0c1d78|here] (and in earlier branches too)

The return type of Tk_GetUserInactiveTime() should have been 'long long', just as other time-related values. We cannot change that in Tk 9.0 any more (due to binary compatibility). But using an additional 'compatibility' stub entry, we can fix it in Tk 9.1 while keeping binary API compatibility. That's done now in Tk 9.1.

Maybe it's possible to enhance the win32 implementation to use return more than 32-bits. If not, not really a big deal ....

Anyway, I'm closing this ticket. Feel free to re-open if something new comes up.


jan.nijtmans added on 2026-07-01 12:14:41:

I'm working on merging it forward


oehhar added on 2026-07-01 11:50:11:

Well, the same line is in core_9_0_branch.

Jan uses LONG_MAX to avoid to limit the 64 bit long type.

I see no reason why this is not needed with core-9-0-branch.

Perhaps we don't build for 32 bit any more. This would be new fdor me...

Thanks, Harald


oehhar added on 2026-07-01 11:43:15:

Jan has merged the branch to core-8-6-branch by cherry-picking, as it started from main, and could not be merged back to core-8-6-branch.

He closed the branch, so no additional work may be done. You may always reopen it.

I suppose:

  • Jan likes the work
  • It is only an issue in 8.6, and not in 9.x.

If this all is ok for you, please close the bug.

Thanks for all, Harald