During daylight saving time transition in late October, we observed a critical issue where scheduled PHP scripts executed twice consecutively - first at 15:00 GMT and then again at 16:00 GMT. The Event Viewer logs showed identical execution patterns:
// First execution at 15:00
Event 100: Task Scheduler started "{GUID}" instance
Event 200: Launched action "php.exe"
Event 201: Successfully completed (return code 0)
// Second execution at 16:00
Event 100: Task Scheduler started "{NEW_GUID}" instance
Event 200: Launched action "php.exe"
Event 201: Successfully completed (return code 0)
The affected infrastructure consisted of:
- Windows Server 2012 R2 Standard Edition
- PHP 5.4 running as console application
- Task Scheduler configured with weekly recurrence (Mon-Fri)
- XML-based task definitions with calendar triggers
After analyzing the XML task definition and Microsoft documentation, we identified this is related to how Windows handles daylight saving time transitions:
<CalendarTrigger>
<StartBoundary>2013-04-17T15:00:20</StartBoundary>
<ScheduleByWeek>
<DaysOfWeek>
<Monday /><Tuesday /><Wednesday />
<Thursday /><Friday />
</DaysOfWeek>
</ScheduleByWeek>
</CalendarTrigger>
The key findings:
- The task scheduler creates duplicate internal triggers during DST transitions
- Microsoft KB2461249 doesn't officially cover Server 2012 but exhibits same symptoms
- Server restart temporarily resolves but doesn't permanently fix the underlying issue
We implemented the following workaround that has proven effective:
// PowerShell script to modify task settings
$TaskName = "\3pm"
$Task = Get-ScheduledTask -TaskName $TaskName
$Task.Settings.StartWhenAvailable = $false
$Task.Settings.AllowHardTerminate = $true
$Task.Settings.ExecutionTimeLimit = "PT1H" // 1 hour limit
Set-ScheduledTask -InputObject $Task
Additional recommendations:
- Implement task locking mechanism in your PHP script:
// PHP implementation $lockFile = '/tmp/task.lock'; if (file_exists($lockFile) && (time()-filemtime($lockFile) < 3600)) { exit(0); // Skip execution if recent run } touch($lockFile);
- Update Windows with latest timezone patches
- Consider migrating to Windows Server 2016+ where this is fixed
We deployed this PowerShell monitoring script to detect duplicate executions:
# Check for duplicate task executions
$Events = Get-WinEvent -FilterHashtable @{
LogName = 'Microsoft-Windows-TaskScheduler/Operational'
ID = 100,201
StartTime = (Get-Date).AddHours(-24)
} | Where-Object {$_.Message -match '\\3pm'}
$ExecutionTimes = $Events |
Where-Object {$_.Id -eq 100} |
Select-Object -ExpandProperty TimeCreated
if ($ExecutionTimes.Count -gt 1) {
$Diff = ($ExecutionTimes[1] - $ExecutionTimes[0]).TotalMinutes
if ($Diff -lt 120) {
Send-MailMessage -To "admin@example.com" -Subject "Duplicate task alert"
}
}
During routine monitoring of our London-based Windows Server 2012 infrastructure, we encountered a peculiar issue where scheduled PHP scripts executed twice consecutively - first at the intended 15:00 GMT and then again at 16:00 GMT. This behavior began immediately following the daylight saving time (DST) transition on October 28th and persisted across two identical servers.
The affected systems shared these characteristics:
- Windows Server 2012 Standard Edition (fully patched)
- Scheduled PHP 5.4 scripts running Monday-Friday
- Task configuration set to "IgnoreNew" for multiple instances
- No apparent resource constraints during execution
The event sequence showed identical successful executions with different process IDs and instance GUIDs:
Event 129 15:00:20 - Launch with PID 2388
Event 100 15:00:20 - Task instance {75a3590f-dec1-4dee-bd27-73d63a50a9d7}
Event 129 16:00:20 - Launch with PID 1224
Event 100 16:00:20 - Task instance {3dd46ca9-c525-4796-86b5-5e513fd45f26}
While Microsoft KB2461249 describes similar behavior on older Windows versions, our Server 2012 systems shouldn't be affected. However, the temporal correlation with the clock change suggests the scheduler's internal timing mechanism may have been impacted.
We developed a PHP-based solution to prevent duplicate execution:
<?php
$lockFile = '/tmp/scheduler.lock';
if (file_exists($lockFile)) {
$fileTime = filemtime($lockFile);
if (time() - $fileTime < 3600) { // 1 hour window
exit("Duplicate execution prevented\n");
}
}
touch($lockFile);
// Main script logic here
?>
- Verify all Windows updates are installed, particularly time-related patches
- Recreate the scheduled tasks from scratch rather than XML import
- Add explicit timezone settings in the task configuration
- Implement the file-based locking mechanism shown above
After server restart and task recreation, one server stopped the duplicate behavior while the other continued. This suggests the issue may be related to both task configuration and system state. Full patching alone didn't resolve the issue, indicating multiple contributing factors.