Hi Markus,
core-libs-dev@openjdk.java.net is the more appropriate list for this
question.
The ProcessHandle info is based directly on the OS information about a
process, there is no separate information stored or kept.
If Linux had a stable way to represent the start time it would be
reflected in the ProcessHandle info.
Changing the clock on any running system is fraught. So many time
related actions depend on linear and/or monotonic progression of time.
Re-reading the boot time would be a performance hit and be subject to a
race condition with setting time.
The process handle also uses the start time to validate a ProcessHandle;
since the cached boot time does not change the value is stable for that
check.
A workaround for your application might be to save the relative start
time by reading the boot time directly from /proc or the relative start
time from /proc.
Roger
On 8/7/19 7:34 AM, Duft Markus wrote:
Hey,
Just checking in to see whether this is a bug, or by design (and where I should
report this if it /is/ a bug :)).
We discovered, that ProcessHandle.Info.startInstant() seems to be non-constant
for a given long running process when restarting the Java VM. We have a
deployment tool (https://bdeploy.io) which monitors processes and tries to
recover running process information when starting up. The general process would
be:
1) Start BDeploy
2) BDeploy starts a child process, records its PID and startInstant to be able
to find it again later
3) BDeploy is stopped (for whatever reason) and the child process keeps running
(we do make sure that this is the case :)).
4) BDeploy is started again, tries to find running processes from its previous
life to resume monitoring.
5) BDeploy reads PID and startInstant from a file, finds a ProcessHandle using
the PID and compares the startInstant. This is to avoid finding wrong processes
when PIDs wrap.
Now we have the problem that this does not work always. Analysis have led us to
the point where we identifier NTPD or manual clock setting as the root cause.
It seems that a system clock change will change the absolute timestamp of a
process start. I had a look at the JDK sources and found that this is actually
true :) Here is what I found out and documented on our own bugtracker:
The relevant java native method on l??inux does this:
/*
* Try to stat and then open /proc/%d/stat
*/
snprintf(fn, sizeof fn, "/proc/%d/stat", pid);
fp = fopen(fn, "r");
...
// Scan the needed fields from status, retaining only ppid(4),
// utime (14), stime(15), starttime(22)
if (4 != sscanf(s, " %*c %d %*d %*d %*d %*d %*d %*u %*u %*u %*u %lu %lu %*d %*d
%*d %*d %*d %*d %llu",
&parentPid, &utime, &stime, &start)) {
return 0; // not all values parsed; return error
}
*totalTime = (utime + stime) * (jlong)(1000000000 /
clock_ticks_per_second);
*startTime = bootTime_ms + ((start * 1000) / clock_ticks_per_second);
...
So the process start time is calculated rela?tive to the system kernel boot
time. The boot time is calculated ONCE when starting the java VM like this:
fp = fopen("/proc/stat", "r");
...
while (getline(&line, &len, fp) != -1) {
if (sscanf(line, "btime %llu", &bootTime) == 1) {
break;
}
}
...
return bootTime * 1000;
However, the /proc/stat btime field does not seem to be constant. When I
manually set the clock 2 minutes ahead, the btime field follows along, and is
now two minutes later than before. Thus any system time correction (manual,
ntpd, ...) will change the system boot time, which will make the timestamp
different, but only after restarting the JVM.
This is IMHO a bug in the JVM. The btime is a relative timestamp (uptime in
nanoseconds if i'm correct). The absolute representation of this timestamp is
calculated on the fly when reading /proc/stat from the current date/time
(assuming that the current date/time is correct). This is not a problem (and
correct!) for a human reader. The field should just never be taken to calculate
another absolute timestamp, which java does...
So we pseudo-have:
bootTime_ms
btime = current-clock-timestamp - kernel-uptime;
proc-start = btime + process-uptime;
All three variables are mutable and may (and will) change. If (and only if)
kernel-uptime and process-uptime are updated correctly, calculating the
absolute start-time will yield a reproducible result only as long as the system
clock does not change.
I'm pretty sure this qualifies as bug, but not whether it's a java a kernel (or
whatever) bug... Any advice, also how to get around this, would be greatly
appreciated. I would really like to avoid hard-coding allowed drift ranges or
something like this, especially as we'll be running into timezone, summer time,
etc. issues AFAICT...
Cheers,
Thanks for ANY help,
Markus
SSI Schäfer IT Solutions GmbH | Friesachstrasse 15 | 8114 Friesach | Austria
Registered Office: Friesach | Commercial Register: 49324 K | VAT no. ATU28654300
Commercial Court: Landesgericht für Zivilrechtssachen Graz
Unsere Hinweise zum Umgang mit personenbezogenen Daten finden Sie
hier<https://www.ssi-schaefer.com/de-at/datenschutz-49548>.
You can find our information on the handling of personal data
here<https://www.ssi-schaefer.com/en-at/privacy-13258>.