Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mac OSX - Timer runs early and causes Elapsed Handler to execute twice. #113089

Closed
speed2048 opened this issue Mar 3, 2025 · 2 comments
Closed

Comments

@speed2048
Copy link

Description

I have a timer that executes every midnight and this issue only occurs on a Mac mini 4.

The code snippet will run run at 23:59:59 and @ 00:00:00

Reproduction Steps

`using System.Timers;

namespace timerTest
{
internal class Program
{
static System.Timers.Timer? timer;

    static void timerElapsed(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine($"Timer triggered @ {DateTime.Now}");

        timer?.Stop();
        timer = null;

        setUpTimer();

    }

    private static DateTime GetNextMidnight()
    {
        return DateTime.Today.AddDays(1);
    }
    static void setUpTimer()
    {

        TimeSpan timeSpan;
       
        timeSpan = GetNextMidnight().Subtract(DateTime.Now);
        Console.WriteLine($"{timeSpan}");
        double tickTime = timeSpan.TotalMilliseconds;
        timer = new System.Timers.Timer(tickTime);
        timer.Elapsed += timerElapsed;
        timer.Start();
    }

    static void Main(string[] args)
    {
        setUpTimer();
        Thread.Sleep(Timeout.Infinite);
    }
}

}
`

Expected behavior

Timer should execute once.

Actual behavior

Timer runs twice.

Timer triggered @ 2025-03-01 11:59:59 PM
Timer triggered @ 2025-03-02 12:00:00 AM

Regression?

I don;t know.

Known Workarounds

Didnt try working on workarounds.

Configuration

.NET SDK:
Version: 9.0.200
Commit: 90e8b202f2
Workload version: 9.0.200-manifests.69179adf
MSBuild version: 17.13.8+cbc39bea8

Runtime Environment:
OS Name: Mac OS X
OS Version: 15.3
OS Platform: Darwin
RID: osx-arm64
Base Path: /usr/local/share/dotnet/sdk/9.0.200/

.NET workloads installed:
[wasm-tools]
Installation Source: SDK 9.0.200
Manifest Version: 9.0.2/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.workload.mono.toolchain.current/9.0.2/WorkloadManifest.json
Install Type: FileBased

[macos]
Installation Source: SDK 9.0.200
Manifest Version: 15.2.9180/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.sdk.macos/15.2.9180/WorkloadManifest.json
Install Type: FileBased

[ios]
Installation Source: SDK 9.0.200
Manifest Version: 18.2.9180/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.sdk.ios/18.2.9180/WorkloadManifest.json
Install Type: FileBased

[maccatalyst]
Installation Source: SDK 9.0.200
Manifest Version: 18.2.9180/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.sdk.maccatalyst/18.2.9180/WorkloadManifest.json
Install Type: FileBased

[maui]
Installation Source: SDK 9.0.200
Manifest Version: 9.0.14/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.sdk.maui/9.0.14/WorkloadManifest.json
Install Type: FileBased

[android]
Installation Source: SDK 9.0.200
Manifest Version: 35.0.39/9.0.100
Manifest Path: /usr/local/share/dotnet/sdk-manifests/9.0.100/microsoft.net.sdk.android/35.0.39/WorkloadManifest.json
Install Type: FileBased

Configured to use loose manifests when installing new manifests.

Host:
Version: 9.0.2
Architecture: arm64
Commit: 80aa709

.NET SDKs installed:
9.0.101 [/usr/local/share/dotnet/sdk]
9.0.102 [/usr/local/share/dotnet/sdk]
9.0.200 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.1 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.1 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.2 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
None

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Mar 3, 2025
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Mar 3, 2025
@jkotas jkotas added area-System.Threading and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Mar 3, 2025
Copy link
Contributor

Tagging subscribers to this area: @mangod9
See info in area-owners.md if you want to be subscribed.

@Clockwork-Muse
Copy link
Contributor

Timers can't wake up at "exactly" the time listed (this is a hardware/OS problem, not a .NET problem). Your application is waking up early, possibly in part due to float precision issues or just the date/time math, and then reschedules itself because it was slightly early. There can also be "spurious wakes", where threads or tasks get scheduled erroneously even without timer expiration (although those will mostly be handled for you at this level).

If you need real scheduling support in an application, there are multiple libraries that can handle this for you; otherwise you will need to account for this yourself.

Scheduling is generally a hard problem. For instance,

private static DateTime GetNextMidnight()

... Due to DST or other timezones shenaniganry, not all days start at midnight (or may have midnight twice).

@dotnet-policy-service dotnet-policy-service bot removed the untriaged New issue has not been triaged by the area owner label Mar 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants