From 74c1657bcb31205d13aff14b63a8ff32d5e8a562 Mon Sep 17 00:00:00 2001 From: Jonah Graham Date: Sat, 22 Nov 2025 11:10:49 -0500 Subject: [PATCH] throw no more handles if a timer could not be created At the moment the code silently fails on calling timerExec if there are no handles left or it fails for other reasons. Relates to https://github.com/eclipse-platform/eclipse.platform.swt/issues/2806 where we can see that we are running out of handles, but the timerExec does not report a failure. On Windows timer handles are related to user objects and are relatively limited (10,000). For Linux and macOS the timers seem only to fail in out of memory situations. --- .../cocoa/org/eclipse/swt/widgets/Display.java | 8 ++++---- .../Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java | 8 ++++---- .../win32/org/eclipse/swt/widgets/Display.java | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java index dc2caec0293..fcfef02be4e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/widgets/Display.java @@ -5343,6 +5343,7 @@ public T syncCall(SwtCallable callable) throws E * @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_NO_HANDLES if a handle could not be obtained for timer creation
  • *
* * @see #asyncExec @@ -5390,14 +5391,13 @@ public void timerExec (int milliseconds, Runnable runnable) { } NSNumber userInfo = NSNumber.numberWithInt(index); NSTimer timer = NSTimer.scheduledTimerWithTimeInterval(milliseconds / 1000.0, timerDelegate, OS.sel_timerProc_, userInfo, false); + if (timer == null) SWT.error (SWT.ERROR_NO_HANDLES); NSRunLoop runLoop = NSRunLoop.currentRunLoop(); runLoop.addTimer(timer, OS.NSModalPanelRunLoopMode); runLoop.addTimer(timer, OS.NSEventTrackingRunLoopMode); timer.retain(); - if (timer != null) { - nsTimers [index] = timer; - timerList [index] = runnable; - } + nsTimers [index] = timer; + timerList [index] = runnable; } long timerProc (long id, long sel, long timerID) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index f0d31654d33..d27a9add319 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -5655,6 +5655,7 @@ public boolean sleep () { * @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_NO_HANDLES if a handle could not be obtained for timer creation
  • *
* * @see #asyncExec @@ -5696,10 +5697,9 @@ public void timerExec (int milliseconds, Runnable runnable) { } else { timerId = GDK.gdk_threads_add_timeout (milliseconds, timerProc, index); } - if (timerId != 0) { - timerIds [index] = timerId; - timerList [index] = runnable; - } + if (timerId == 0) SWT.error (SWT.ERROR_NO_HANDLES); + timerIds [index] = timerId; + timerList [index] = runnable; } long timerProc (long i) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index cda18f6fc82..9a763aca3d5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -4961,6 +4961,7 @@ public T syncCall(SwtCallable callable) throws E * @exception SWTException
    *
  • ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  • *
  • ERROR_DEVICE_DISPOSED - if the receiver has been disposed
  • + *
  • ERROR_NO_HANDLES if a handle could not be obtained for timer creation
  • *
* * @see #asyncExec @@ -5002,10 +5003,9 @@ public void timerExec (int milliseconds, Runnable runnable) { } } long newTimerID = OS.SetTimer (hwndMessage, timerId, milliseconds, 0); - if (newTimerID != 0) { - timerList [index] = runnable; - timerIds [index] = newTimerID; - } + if (newTimerID == 0) SWT.error (SWT.ERROR_NO_HANDLES); + timerList [index] = runnable; + timerIds [index] = newTimerID; } boolean translateAccelerator (MSG msg, Control control) {