Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit e4a35b9

Browse files
tmdsstephentoub
authored andcommitted
Fix Process StartTime offset on Linux due to device sleeping (#25312)
* Fix Process StartTime offset on Linux due to device sleeping * PR feedback * uptimeFile -> UptimeFile * remove Debug.Assert * pal_io.c: revert unrelated fix
1 parent b28e05a commit e4a35b9

File tree

3 files changed

+39
-17
lines changed

3 files changed

+39
-17
lines changed

src/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@
435435
<Reference Include="System.Diagnostics.FileVersionInfo" />
436436
<Reference Include="System.Diagnostics.Tools" />
437437
<Reference Include="System.IO.FileSystem" />
438+
<Reference Include="System.Memory" />
438439
<Reference Include="System.Resources.ResourceManager" />
439440
<Reference Include="System.Runtime" />
440441
<Reference Include="System.Runtime.Extensions" />

src/System.Diagnostics.Process/src/System/Diagnostics/Process.Linux.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using System;
56
using System.Collections.Generic;
67
using System.ComponentModel;
8+
using System.Globalization;
79
using System.IO;
810
using System.Text;
911

@@ -57,6 +59,42 @@ internal DateTime StartTimeCore
5759
}
5860
}
5961

62+
/// <summary>Computes a time based on a number of ticks since boot.</summary>
63+
/// <param name="timespanAfterBoot">The timespan since boot.</param>
64+
/// <returns>The converted time.</returns>
65+
internal static DateTime BootTimeToDateTime(TimeSpan timespanAfterBoot)
66+
{
67+
// Use the uptime and the current time to determine the absolute boot time.
68+
DateTime bootTime = DateTime.UtcNow - Uptime;
69+
70+
// And use that to determine the absolute time for timespan.
71+
DateTime dt = bootTime + timespanAfterBoot;
72+
73+
// The return value is expected to be in the local time zone.
74+
// It is converted here (rather than starting with DateTime.Now) to avoid DST issues.
75+
return dt.ToLocalTime();
76+
}
77+
78+
/// <summary>Gets the elapsed time since the system was booted.</summary>
79+
private static TimeSpan Uptime
80+
{
81+
get
82+
{
83+
// '/proc/uptime' accounts time a device spends in sleep mode.
84+
const string UptimeFile = Interop.procfs.ProcUptimeFilePath;
85+
string text = File.ReadAllText(UptimeFile);
86+
87+
double uptimeSeconds = 0;
88+
int length = text.IndexOf(' ');
89+
if (length != -1)
90+
{
91+
Double.TryParse(text.AsReadOnlySpan().Slice(0, length), NumberStyles.AllowDecimalPoint, NumberFormatInfo.InvariantInfo, out uptimeSeconds);
92+
}
93+
94+
return TimeSpan.FromSeconds(uptimeSeconds);
95+
}
96+
}
97+
6098
/// <summary>Gets execution path</summary>
6199
private string GetPathToOpenFile()
62100
{

src/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -473,23 +473,6 @@ internal static TimeSpan TicksToTimeSpan(double ticks)
473473
return TimeSpan.FromSeconds(ticks / (double)ticksPerSecond);
474474
}
475475

476-
/// <summary>Computes a time based on a number of ticks since boot.</summary>
477-
/// <param name="timespanAfterBoot">The timespan since boot.</param>
478-
/// <returns>The converted time.</returns>
479-
internal static DateTime BootTimeToDateTime(TimeSpan timespanAfterBoot)
480-
{
481-
// Use the uptime and the current time to determine the absolute boot time. This implementation is relying on the
482-
// implementation detail that Stopwatch.GetTimestamp() uses a value based on time since boot.
483-
DateTime bootTime = DateTime.UtcNow - TimeSpan.FromSeconds(Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency);
484-
485-
// And use that to determine the absolute time for timespan.
486-
DateTime dt = bootTime + timespanAfterBoot;
487-
488-
// The return value is expected to be in the local time zone.
489-
// It is converted here (rather than starting with DateTime.Now) to avoid DST issues.
490-
return dt.ToLocalTime();
491-
}
492-
493476
/// <summary>Opens a stream around the specified file descriptor and with the specified access.</summary>
494477
/// <param name="fd">The file descriptor.</param>
495478
/// <param name="access">The access mode.</param>

0 commit comments

Comments
 (0)