Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2738d7cc86 | |||
| 9f3b8110f7 | |||
| 92ddd08fda | |||
| 9ad218d44f |
+1
-1
@@ -63,5 +63,5 @@ lib/
|
||||
# Subagent-driven-development git worktrees
|
||||
.worktrees/
|
||||
|
||||
# Local OPC UA validation runs; selected receipts belong under docs/plans/evidence.
|
||||
# OPC UA SDK upgrade verification artifacts
|
||||
/artifacts/opcua2/
|
||||
|
||||
@@ -68,7 +68,7 @@ No optional ManagedSession/DI/AOT/cluster redesign, trust relaxation, silent war
|
||||
- G1 restored 2.0 graph / break inventory: passed; compilation convergence subsequently passed G2.
|
||||
- G2 compilation convergence: passed; whole-solution Release builds have zero warnings/errors and temporary migration assets are removed.
|
||||
- G3 behavioral/security/interoperability: pending.
|
||||
- G4 lifecycle/performance/publish: failed/open for the canonical RSS gate (#799); scoped client lifecycle/publish results are recorded below.
|
||||
- G4 lifecycle/performance/publish: pending.
|
||||
- Astra security/ownership source findings: closed for the reviewed identity, history, audit and browse changes; final release review remains pending.
|
||||
|
||||
No upgraded artifact is approved for release.
|
||||
@@ -321,24 +321,16 @@ The same-cap self-contained **Linux ARM64 server/node-manager workload also
|
||||
failed**, at **248 cycles / 61 restarts / 903.508 seconds**: RSS353,931,264
|
||||
exceeded351,850,496 bytes (cycle3 baseline+128MiB). Managed memory~20.5MB,
|
||||
descriptors189, PKI descriptors0, cached stores2 and logical collections remained
|
||||
bounded. Runtime10.0.14, SDK 2.0.1; test/container/launcher fail. This broadens
|
||||
bounded. Runtime10.0.14, SDK2.0.1; test/container/launcher fail. This broadens
|
||||
#799 beyond macOS; no complete/two-hour pass exists.
|
||||
[Selected Linux failed-run receipts](evidence/2026-11-10-opcua2/server-linux-soak-failed.json)
|
||||
retain hashes, unchanged limits, positive descriptor controls and failure.
|
||||
|
||||
The independent root-owned actual production Shared/driver/live-reinitialize/
|
||||
browser lifecycle run on Linux **passed after 7,200.984 seconds**, with 5,420 cycles,
|
||||
10,840 rounds per product, 10,840 additional live driver reinitializations and
|
||||
43,360 verified certificate-manager disposals. All 543 samples had zero weak product
|
||||
survivors and zero open PKI descriptors. Final managed memory was 3,988,520 bytes,
|
||||
RSS 86,102,016 bytes and global FDs 148. Own certificates remained unchanged; the
|
||||
manager disposal positive control passed. Container/test exit 0 and the real
|
||||
monotonic duration guard passed. [Full counter/hash receipts](../../scripts/validation/opcua-client-lifecycle/evidence/2026-11-10-full/verification.json)
|
||||
record source `c25561c6`, exact SDK 2.0.1 and Linux ARM64 runtime 10.0.3. The later
|
||||
HG 1.0 consumer change is independently tested and does not relabel these artifacts.
|
||||
This is a completed client lifecycle gate, **not an RSS performance-budget or full
|
||||
G4 pass**. Its workload does not replace the failed canonical server soak.
|
||||
G4 and release approval remain open.
|
||||
browser lifecycle run on Linux is still in progress. Its final elapsed duration,
|
||||
counters, resource limits and completion/exit guards must be recorded separately.
|
||||
A short diagnostic, a running process, or a different workload is never substituted
|
||||
for a required passing gate. G4 and release approval remain open.
|
||||
|
||||
|
||||
## Final integrated source review and diagnostic instrumentation
|
||||
@@ -396,156 +388,7 @@ only a **prospective diagnostic saturation design**, recorded in the report:
|
||||
384 fixed canonical cycles/96 restarts plus one settling cycle within1,800 seconds;
|
||||
fixed traced windows321–352 and353–384; zero generated-factory compilations,
|
||||
new SDK assembly loads and lost events; ownership checks active throughout.
|
||||
That experiment had not run at that review; its later diagnostic result is recorded below and cannot pass G4. Matched full acceptance requires
|
||||
That experiment has not run and cannot pass G4. Matched full acceptance requires
|
||||
an original-SDK adapter for the identical canonical workload and at least7,200
|
||||
seconds **after** a prospectively reviewed fixed warmup. Historical failures and
|
||||
macOS native retention remain open in #799. No release approval was given.
|
||||
|
||||
|
||||
## Included HistorianGateway 1.0 consumer change
|
||||
|
||||
The user's added [historiangw#131](https://gitea.dohertylan.com/dohertj2/historiangw/issues/131)
|
||||
was delivered independently on OtOpcUa master `230cef4e`, then merged into the
|
||||
SDK2 branch at `67bc6123`. Both real published Client/Contracts packages are 1.0.0;
|
||||
the adapter maps `AllowUntrustedServerCertificate = UseTls && configuredOptOut`
|
||||
and retains strict TLS defaults and h2c certificate-option filtering. Astra
|
||||
approved source/security and corrected real-wire tests. Full master Release
|
||||
build: 0 warnings/errors; Gateway 523 passed/6 existing live skips, Runtime1,002
|
||||
passed/3 existing retired-fixture skips, zero failures, execution guards passed.
|
||||
The three new wire tests prove typed TLS rejection before RPC, explicit opt-out
|
||||
success and h2c success. The issue was closed with a verification comment after
|
||||
master push; [immutable package/test receipt](evidence/2026-11-10-historiangw-131.json).
|
||||
Independent actual-package SDK2 Gateway verification also passed 523/0/6.
|
||||
|
||||
The integrated SDK2/HG 1.0 solution built with 0 warnings/errors in 46.91 seconds.
|
||||
CI3 and the corrected follow-up run are recorded below; every command preserves
|
||||
test/guard exits and the 12,000 execution floor. CI2 remains historical pre-HG 1.0 evidence.
|
||||
|
||||
All four self-contained Host/CLI publishes and actual Linux Host two-start/stop
|
||||
checks were repeated on the HG 1.0 graph at `f2a8ce13`: all passed. Both Host
|
||||
artifacts contain the exact published 1.0.0 Client/Contracts DLLs; the Foundation
|
||||
SDK family remains 2.0.1. Six strict HMAC/peer cases, two Good published-CLI reads,
|
||||
preserved certificate identity and zero task-secret matches passed. See the
|
||||
[fresh publication/runtime report](evidence/2026-11-10-opcua2/publish-smoke-hg100.md).
|
||||
Windows actual install/runtime #800 and live/paired-environment #801 remain pending.
|
||||
|
||||
|
||||
## CI3 investigation and corrected final verification
|
||||
|
||||
The post-HG 1.0 full CI3 run at `f2a8ce13` produced **63 TRX, 19,124 total,
|
||||
18,489 executed, 18,472 passed, 17 failed and 635 existing skipped** results.
|
||||
Test exit 1 and execution guard 0 are retained in
|
||||
[the complete summary](evidence/2026-11-10-opcua2/solution-tests3.json).
|
||||
Eleven failures match the established baseline issues #796/#798. Five browser
|
||||
failures came from a task simulator with differing advertised/internal and host
|
||||
ports. Matching those ports restores browser 5/5 and driver 5/5 with no source
|
||||
change. Actual SDK1.5.378.182 browser binaries also fail the different-port
|
||||
advertisement with the same DNS error: [baseline NAT parity](evidence/2026-11-10-opcua2/browser-nat-parity.md).
|
||||
The preexisting browser capability gap is [#806](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/806),
|
||||
not a new SDK2 behavior or a security-policy workaround.
|
||||
|
||||
The final failure was a preexisting Runtime test-ordering race: an EF-presence
|
||||
wait captured the first apply before its later NodeAdded announcement. A gated
|
||||
controlled reproduction proves 1→2 with one EF and one announcement. The narrow
|
||||
repair awaits correlated clean completion replies for both rebuilds, retaining
|
||||
all idempotence assertions and existing budgets. Astra reviewed source causality
|
||||
and RED/GREEN proof. SDK2 and independent SDK1.5 owning Runtime suites each pass
|
||||
**1,002 tests, zero failures and 3 existing skips**. The test-only fix landed on
|
||||
master `52d1373e`, merged at `75057d8c`; [#805](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/805)
|
||||
closed with validation. [Exact repair evidence](evidence/2026-11-10-opcua2/rebuild-test-barrier.md).
|
||||
No product code, expected result, timing budget or skip was changed.
|
||||
|
||||
The complete solution rebuilt at `75057d8c` with **zero warnings/errors**, 26.61 s.
|
||||
Fresh full CI4 with the corrected simulator and completion-barrier repair completed
|
||||
at `75057d8c`: **63 TRX, 19,124 total, 18,489 executed, 18,478 passed, 11 failed,
|
||||
635 existing skips**. Test exit **1**, execution guard **0** at floor12,000.
|
||||
All eleven remaining failures are the established ten PercentGood cases (#796)
|
||||
and one ScriptWorker timing assertion (#798). The fixture and rebuild-ordering
|
||||
cases pass in this same full run, with no additional failure classes or new skips.
|
||||
[Versioned counters, exact failures and per-project hashes](evidence/2026-11-10-opcua2/solution-tests4.json)
|
||||
retain the nonzero status. CI3 remains available; this baseline-matching result
|
||||
is **not a green solution run**. Task-owned simulator was removed after completion.
|
||||
|
||||
## Canonical candidate generated-factory saturation result
|
||||
|
||||
The exact immutable bundle reviewed by Astra completed **384 canonical cycles,
|
||||
96 restarts and one settling cycle in 1,425.242 seconds**, inside the fixed 1,800-second
|
||||
cutoff. Both fixed trace windows and the continuous attached interval had zero
|
||||
SDK generated-factory JIT/load events, zero new SDK assembly loads and zero lost
|
||||
events. The observer detached/drained before settling; shutdown ownership checks
|
||||
passed. This meets only the selected generated-factory readiness criterion.
|
||||
|
||||
The unchanged cold cap rejected at cycle 248: RSS 362,409,984 >358,838,272 bytes.
|
||||
The original assertion was rethrown; test/container/launcher exit 1, no ordinary
|
||||
completion or full-duration flag. Peak RSS 394,956,800 bytes; final managed memory
|
||||
19,974,280 bytes. Allocation StackTrace tracking was enabled, so this is additional
|
||||
instrumented diagnostic overhead and cannot serve as uninstrumented performance
|
||||
or acceptance evidence. [Scoped report and hashed receipts](evidence/2026-11-10-opcua2/saturation-candidate.md).
|
||||
#799 and G4 remain failed/open. A matched original-SDK canonical adapter is being
|
||||
prepared before any further acceptance-protocol review; no warmed replacement
|
||||
baseline, budget waiver, factory/runtime setting or production patch was adopted.
|
||||
|
||||
|
||||
## Original canonical adapter limitation and final review boundary
|
||||
|
||||
The [original-SDK canonical adapter](../../scripts/validation/opcua-lifecycle-memory/baseline-canonical/README.md)
|
||||
compiles against the unchanged `83ed880e` publications with zero warnings/errors;
|
||||
its package/input/source hashes are preserved. A short normal-cycle control
|
||||
completed encrypted sessions, typed writes/readbacks, all ten history calls,
|
||||
revocation, surgery/rebuild, stalled-read recovery, subscription cleanup and both
|
||||
client closes. The retained closed Session object still held one browse and six
|
||||
history points while SessionManager had zero active sessions; the copied assertion
|
||||
fails with exit1, including after a separate fixed250ms observation. Exact1.5
|
||||
binary inspection shows Close removes diagnostics, while Dispose clears those
|
||||
lists. Held-object state does not prove live server retention or an unbounded leak.
|
||||
|
||||
A separate active-session restart control cleared the observable session/
|
||||
subscription/item/CP counts, then returned **exit2: unsupported ownership parity**.
|
||||
Original ApplicationInstance/CertificateValidator have no SDK2 manager-disposal
|
||||
observable; cached store references1→1 are not file-handle counts. Unsupported
|
||||
metrics were not fabricated as zeros. This is not a passing four-cycle sequence,
|
||||
a matched process-memory host, an accepted RSS denominator or a long-run result.
|
||||
Astra independently verified208 reference hashes, all short-run projections and
|
||||
the exact immutable close/dispose behavior. The diagnostic package is reviewable;
|
||||
shared semantic/token/weak-root/resource-owner checks remain prerequisites to a
|
||||
new acceptance procedure.
|
||||
|
||||
Astra's final integrated verdict is **source/security review closed, release HOLD**.
|
||||
It independently verified all63 final CI4 TRX hashes/counters and exact baseline
|
||||
failure attribution, the two-hour client receipts and428-file recursive manifest,
|
||||
the candidate saturation result and original failure preservation, and the
|
||||
original adapter's explicit limitations. No new must-fix migration source/security
|
||||
finding remains. **CI remains red on11 baseline cases; G3 external evidence and
|
||||
G4 resource/performance acceptance remain unresolved.** #799, #800, #801 and
|
||||
ScadaBridge#121 stay open. Neither an SDK version substitution, production crypto/
|
||||
session-factory workaround, resource-cap waiver nor warmed acceptance baseline
|
||||
was approved. SDK2 remains on draft PR#802; it is not merged to master or deployed.
|
||||
|
||||
## Follow-on #799 close ownership and native attribution
|
||||
|
||||
The [candidate bounded close control](evidence/2026-11-10-opcua2/close-ownership-candidate.md)
|
||||
at `564f1091` passed with one abandoned browse and six abandoned history points.
|
||||
Old authentication returns exactly BadSessionIdInvalid; old continuation tokens
|
||||
are rejected without a history-backend read while fresh-session positives work.
|
||||
All 23 old-object weak targets collect with the same host still running; all 13
|
||||
application/server/manager/core/store targets collect after normal shutdown.
|
||||
SDK2's stronger `(0,0)` closed-list check, two manager-disposal checks, empty
|
||||
caches and zero PKI descriptors remain enforced. Astra verified the actual TRX.
|
||||
Six affected history tests also pass; their original launcher mistakenly expected
|
||||
seven, and the retained false guard receipt has a separate independently reviewed
|
||||
six-test source/TRX correction. No failed test was relabelled or rerun for that fix.
|
||||
|
||||
The [fixed macOS store-versus-registry control](../../scripts/validation/opcua-lifecycle-memory/native-retention/README.md)
|
||||
completed its execution/ownership checks, **not native-retention acceptance**.
|
||||
Two hundred configured-store acquisitions leave AppleDatabase inventory 3→203;
|
||||
registry AddRefs remain 3→3. After normal disposal and five seconds idle, both
|
||||
arms have zero SDK certificate owners, runtime-tracked temporary keychains,
|
||||
temporary-keychain files, keychain descriptors and PKI descriptors. The installed
|
||||
runtime calls CFRelease after native deletion; a missing managed release is not
|
||||
indicated. Native ownership/delete status, complete RSS attribution and a supported
|
||||
mitigation remain unresolved. Registry substitution would change deliberate
|
||||
configured-store replacement semantics and was not adopted.
|
||||
|
||||
These results leave the original cold RSS failures and #799/G4 unchanged. The
|
||||
[prospective resolution procedure](../../scripts/validation/opcua-lifecycle-memory/RESOLUTION.md)
|
||||
is explicitly a design draft, not approval to launch a warmed acceptance run.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
This operator runbook accompanies [#782](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/782),
|
||||
the [implementation plan](2026-11-10-opcua-sdk-2-upgrade.md) and
|
||||
[execution evidence](2026-11-10-opcua-sdk-2-evidence.md). Gitea is the single
|
||||
status system. This runbook was reconciled with SDK2/HG1.0 checkout `f2a8ce13` and the
|
||||
status system. This runbook was reconciled with checkout `aa9af0dc` and the
|
||||
commit-specific local receipts linked below. It records local validation, not
|
||||
operator release approval or a fleet deployment. Receipt revisions vary; use each
|
||||
report's full source/artifact identity rather than treating every result as a test
|
||||
@@ -52,9 +52,8 @@ also touches gateway/retired sidecar paths outside this SDK rollout.
|
||||
SDK FILETIME-zero maps to the existing CLR unset-time sentinel at history boundaries.
|
||||
- No new historian backend, companion specification, PubSub, ManagedSession, AOT or
|
||||
cluster rolling-upgrade capability is claimed. HistorianGateway Client/Contracts
|
||||
**1.0.0** is on OtOpcUa master `230cef4e` and merged into this candidate
|
||||
(historiangw#131 closed after published-package/TLS verification). The preceding
|
||||
0.4.0 alignment closed #119. The live gateway gate historiangw#78 remains separate.
|
||||
**0.4.0** is already on gateway master `16111a5e` (historiangw#119 closed);
|
||||
the real gateway gate historiangw#78 remains separate from package alignment.
|
||||
- Certificate creation correction `bd3143b7` uses the SDK's **12-month** default
|
||||
instead of treating 2048 as months. The separate RSA minimum stays 2048 bits;
|
||||
existing certificates/private-key bytes and PKI identity are retained.
|
||||
@@ -73,21 +72,16 @@ unexecuted operator or duration gates. Keep secrets out of logs and release reco
|
||||
| Actual ScadaBridge adapter | **18 None/API-key cases pass**, nine against each server. Encrypted attempts fail against both due to the preexisting own-certificate configuration gap, [ScadaBridge#121](https://gitea.dohertylan.com/dohertj2/ScadaBridge/issues/121); secure interoperability is blocked. [Consumer receipts](../../scripts/validation/scadabridge-sdk-compatibility/). |
|
||||
| Local historian backends | SQL Server **195/195** on each version; QuestDB **233 passed, 0 failed, 1 existing opt-in race-stress skip** on each. Case outcomes match. [Backend matrix](evidence/2026-11-10-opcua2/backend-matrix.md). This is not live AVEVA evidence. |
|
||||
| Bounded performance subset | Three warmed measurements per version: median rebuild **17→15 ms**, removal **81→80 ms**, equal visit counts. [Benchmark scope/load caveats](evidence/2026-11-10-opcua2/lock-benchmarks.md); these are not full wire-throughput, p95 or steady-RSS approval. |
|
||||
| Publish/package and Linux smoke | **Four** self-contained Linux ARM64/Windows x64 Host/CLI publishes pass. Actual Linux full Host passes **two start/stop cycles**, strict security/health checks and unchanged PKI. [Fresh HG1.0 artifact hashes and runtime receipts](evidence/2026-11-10-opcua2/publish-smoke-hg100.md). Both Hosts contain Client/Contracts1.0.0; Foundation remains2.0.1. Windows execution is still pending. |
|
||||
| Production client lifecycle | **7,200.984 seconds,5,420 cycles,43,360 verified manager disposals**, zero weak product survivors and PKI descriptors across543 samples. [Exact source/runtime/counter receipts](../../scripts/validation/opcua-client-lifecycle/evidence/2026-11-10-full/verification.json). This is a client lifecycle pass, not a server RSS or full G4 pass. |
|
||||
| Publish/package and Linux smoke | **Four** self-contained Linux ARM64/Windows x64 Host/CLI publishes pass. Actual Linux full Host passes **two start/stop cycles**, strict security/health checks and unchanged PKI. [Per-artifact revisions, SHA-256 manifests and runtime receipts](evidence/2026-11-10-opcua2/publish-smoke.md). Windows execution is still pending. |
|
||||
| Source review | Independent reviews covered identity, ownership, aggregate preservation, hierarchy and filtered audit paths. [Review scope](2026-11-10-opcua-sdk-2-evidence.md#integrated-implementation-and-source-reviews). Source review is not release approval. |
|
||||
|
||||
The final corrected CI-equivalent run at `75057d8c` completed with **63 TRX,
|
||||
19,124 total, 18,489 executed, 18,478 passed, 11 failed and 635 existing skips**.
|
||||
Test exit **1**; execution guard **0** at floor12,000. It is not green: the eleven
|
||||
failures are ten PercentGood cases and one ShadowMode250ms assertion, independently
|
||||
reproduced on baseline. [Final counters/failures/project hashes](evidence/2026-11-10-opcua2/solution-tests4.json).
|
||||
CI3's extra five simulator-advertisement failures were corrected by a directly
|
||||
reachable matching-port fixture; the baseline Runtime test-ordering race was fixed
|
||||
through correlated completion barriers (#805, master52d1373e). Both corrections
|
||||
pass in the final full run. The retained CI3 report and original SDK1.5 NAT parity
|
||||
are in the [main evidence](2026-11-10-opcua-sdk-2-evidence.md#ci3-investigation-and-corrected-final-verification);
|
||||
preexisting browser NAT behavior remains #806.
|
||||
The second full CI-equivalent run completed with **63 TRX, 19,121 discovered,
|
||||
18,486 executed, 18,475 passed, 11 failed and 635 existing skips**. Test exit was
|
||||
**1**; execution guard exit was **0** at floor 12,000. It is not green: the exact
|
||||
failures are ten unchanged PercentGood cases and one ShadowMode 250 ms timing
|
||||
assertion (585.7377 ms), independently reproduced on baseline, with no new failure
|
||||
classes. Summary: `/tmp/opcua2-ci2-summary.json`; final provenance is in the
|
||||
[main evidence](2026-11-10-opcua-sdk-2-evidence.md#solution-performance-and-package-evidence).
|
||||
The ten PercentGood failures are tracked in
|
||||
[#796](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/796), and the separately
|
||||
reproduced baseline ScriptWorker timing failure is
|
||||
@@ -103,17 +97,9 @@ exceeded **351,850,496 bytes**. Its retained result is
|
||||
`/tmp/opcua2-server-linux-full-20261110/task/results/soak.trx`.
|
||||
[#799](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/799) owns investigation;
|
||||
no cap waiver or two-hour server pass is recorded. The distinct actual-production
|
||||
Shared/driver/reinitialize/browser Linux lifecycle run passed its actual two-hour
|
||||
duration and cleanup checks, as recorded above; it does not replace this failed
|
||||
server workload. See [long-run scope](2026-11-10-opcua-sdk-2-evidence.md#resource-finding-and-long-run-scope)
|
||||
Shared/driver/reinitialize/browser two-hour Linux lifecycle run is still active;
|
||||
its partial duration is not a pass. See [long-run scope](2026-11-10-opcua-sdk-2-evidence.md#resource-finding-and-long-run-scope)
|
||||
for instrumentation limitations and final-result updates.
|
||||
The fixed candidate saturation diagnostic later met its selected generated-factory
|
||||
criterion, but retained the cold RSS rejection and exit1. The original-SDK adapter
|
||||
records partial wire coverage and unsupported ownership/process-memory parity;
|
||||
it supplies no approved performance denominator. See [scoped saturation result](evidence/2026-11-10-opcua2/saturation-candidate.md)
|
||||
and [original adapter limitations](../../scripts/validation/opcua-lifecycle-memory/baseline-canonical/README.md).
|
||||
Astra's final source/security review is closed; release remains on HOLD.
|
||||
|
||||
|
||||
| Operator release field | Still required before its release decision |
|
||||
|---|---|
|
||||
@@ -333,11 +319,9 @@ thresholds or count absent environments as passed.
|
||||
Local build, security/wire, aggregate, backend, compatibility, publish and Linux
|
||||
smoke evidence is linked above with its actual scope and revisions. The server
|
||||
RSS gate is failed (#799), full CI retains the 11 baseline failures (#796/#798),
|
||||
the client lifecycle run completed two hours with cleanup checks passed, secure
|
||||
ScadaBridge interoperability is blocked (ScadaBridge#121), and
|
||||
the client lifecycle run is still active, secure ScadaBridge interoperability is
|
||||
blocked (ScadaBridge#121), and
|
||||
Windows/live AVEVA/pair/operator gates remain pending (#800/#801). No fleet rollout
|
||||
or rollback has been executed. The final post-HG1.0 corrected full run retains
|
||||
only the eleven independently reproduced baseline failures; earlier failed runs
|
||||
remain recorded. The coordinator records remaining decisions in #782 and the main
|
||||
evidence; none is inferred from a
|
||||
or rollback has been executed. The coordinator records the final client-lifecycle result
|
||||
and remaining decisions in #782 and the main evidence; none is inferred from a
|
||||
passing subset or cross-published artifact.
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# SDK1.5 Browser different-port NAT parity
|
||||
|
||||
Read-only application validation using existing Release Browser integration DLLs in `/Users/dohertj2/.codex/worktrees/historiangw-client-040/OtOpcUa` (current HEAD `52d1373e8129b7f4f0ea2e35f86a8a5d0ed1de36`). No repository edits, build, or restore. DLL dependency graph confirms all five OPCFoundation packages `1.5.378.182`; exact DLL hashes/package versions are in `metadata.json`.
|
||||
|
||||
One task-owned fixture was started from cached `mcr.microsoft.com/iotedge/opc-plc:2.14.10` with `--pn=50000 --ut --aa --alm`, hostname `otopcua-sdk1-browser-nat-parity`, and localhost ephemeral mapping `127.0.0.1:32773 -> 50000`. Image ID/digest and Docker configuration are recorded in `container-metadata.txt` and `image-digest.txt`. No shared fixture, volume, or port was changed.
|
||||
|
||||
All five original SDK1.5 Browser integration cases failed: **0 passed, 5 failed, 0 skipped**; test exit1, execution guard exit0. Each failed with `System.Net.Sockets.SocketException: nodename nor servname provided, or not known` in the SDK1.5 `DefaultSessionFactory.CreateChannelAsync/CreateAsync` path. `browser-sdk1-nat.trx` and `test.log` contain the actual failures.
|
||||
|
||||
A standalone scratch discovery probe referencing those exact baseline `Opc.Ua.*` DLLs called public `DiscoveryClient.CreateAsync` and `GetEndpointsAsync` against localhost:32773. It succeeded (exit0) and captured all seven advertised endpoints at `opc.tcp://otopcua-sdk1-browser-nat-parity:50000/`, including SecurityPolicy.None/MessageSecurityMode.None. See `get-endpoints.log` and `discovery-probe/{Program.cs,probe.csproj}`. The advertised hostname/port are therefore the actual discovery response, not inferred from configuration alone.
|
||||
|
||||
This establishes the same browser failure on SDK1.5 when discovery advertises an unreachable Docker hostname/internal port. It supports classification as a preexisting NAT/advertisement limitation exposed by the test fixture mapping, rather than an SDK2-only regression. Root's matching-port SDK2 fixture pass is separate evidence.
|
||||
|
||||
Command:
|
||||
|
||||
```sh
|
||||
OPCUA_SIM_ENDPOINT=opc.tcp://127.0.0.1:32773 dotnet test tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.IntegrationTests/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.IntegrationTests.csproj -c Release --no-build --no-restore --logger 'trx;LogFileName=browser-sdk1-nat.trx' --results-directory /tmp/opcua-browser-sdk1-nat-parity
|
||||
MIN_EXECUTED=1 bash scripts/ci/assert-not-all-skipped.sh /tmp/opcua-browser-sdk1-nat-parity/browser-sdk1-nat.trx
|
||||
```
|
||||
|
||||
Cleanup removed only `otopcua-sdk1-browser-nat-parity`; cleanup exit0 and exact-name absence recorded in `cleanup.log`. No source/issue changes or commits.
|
||||
|
||||
|
||||
The baseline browser limitation remains open in [#806](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/806). This migration retains its behavior; the fixture is configured as a directly reachable endpoint with identical host/internal/advertised ports. Focused SDK2 browser5/5 and driver5/5 passed after that correction, with no source changes.
|
||||
@@ -1,200 +0,0 @@
|
||||
{
|
||||
"issues": {
|
||||
"ordering": "#805 closed; master52d1373e",
|
||||
"nat": "#806 open; SDK1.5 parity confirms preexisting limitation"
|
||||
},
|
||||
"evidence": {
|
||||
"controlledRed": {
|
||||
"sha256": "986e32c042f8b8525af44647f52d2defbf759ab122eb7494a05d77a0e1e4fbf9",
|
||||
"counters": {
|
||||
"total": "1",
|
||||
"executed": "1",
|
||||
"passed": "0",
|
||||
"failed": "1",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 0,
|
||||
"Failed": 1,
|
||||
"NotExecuted": 0
|
||||
}
|
||||
},
|
||||
"controlledGreen": {
|
||||
"sha256": "cbc3bf65bc7ad915f8b8697c260181f3cc01321a4904137dcca6fd4ac09b047d",
|
||||
"counters": {
|
||||
"total": "1",
|
||||
"executed": "1",
|
||||
"passed": "1",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 1,
|
||||
"Failed": 0,
|
||||
"NotExecuted": 0
|
||||
}
|
||||
},
|
||||
"sdk2Runtime": {
|
||||
"sha256": "238ecd1b10df3d9e173d428f2760c35b5e293b4db67f3e9a2a46d2d9988a27f2",
|
||||
"counters": {
|
||||
"total": "1005",
|
||||
"executed": "1002",
|
||||
"passed": "1002",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 1002,
|
||||
"Failed": 0,
|
||||
"NotExecuted": 3
|
||||
}
|
||||
},
|
||||
"sdk1Runtime": {
|
||||
"sha256": "e6b378d324a91d08159b59f675d10af2207a745afc6e0c846564c39ac144b58a",
|
||||
"counters": {
|
||||
"total": "1005",
|
||||
"executed": "1002",
|
||||
"passed": "1002",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 1002,
|
||||
"Failed": 0,
|
||||
"NotExecuted": 3
|
||||
}
|
||||
},
|
||||
"browserCorrectedFixture": {
|
||||
"sha256": "ed9db0d9545fef17e8b43429a962a36936b551c2de03535be4b7983343d42ecd",
|
||||
"counters": {
|
||||
"total": "5",
|
||||
"executed": "5",
|
||||
"passed": "5",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 5,
|
||||
"Failed": 0,
|
||||
"NotExecuted": 0
|
||||
}
|
||||
},
|
||||
"driverCorrectedFixture": {
|
||||
"sha256": "dc2ac55ca296474d767b29ddca2feaa027cec5793ab6ac6a28a10c98dfb2cb56",
|
||||
"counters": {
|
||||
"total": "5",
|
||||
"executed": "5",
|
||||
"passed": "5",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 5,
|
||||
"Failed": 0,
|
||||
"NotExecuted": 0
|
||||
}
|
||||
},
|
||||
"sdk1BrowserNatBaseline": {
|
||||
"sha256": "7111ac68dd46bb1931b0e8c3b4bbb3b85588dbcd94758aec5fcb3e6e205b0487",
|
||||
"counters": {
|
||||
"total": "5",
|
||||
"executed": "5",
|
||||
"passed": "0",
|
||||
"failed": "5",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"outcomes": {
|
||||
"Passed": 0,
|
||||
"Failed": 5,
|
||||
"NotExecuted": 0
|
||||
}
|
||||
},
|
||||
"actorMasterCandidateSourceDiff": {
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"bytes": 0
|
||||
},
|
||||
"sdk1GetEndpoints": {
|
||||
"sha256": "c4400f696ce3a8e8cdc49a4dedc06e4969584cfb47a6ada28c28bf91f75189f7",
|
||||
"bytes": 858
|
||||
}
|
||||
},
|
||||
"expectedRedFailureRetained": true,
|
||||
"newProductChanges": false
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,41 +0,0 @@
|
||||
# Candidate close and weak-root control
|
||||
|
||||
The final bounded control at `564f10914357fc34db303b2faf030907663e6779`
|
||||
passed: one test executed, one passed, no skips; runner elapsed 10.082 seconds.
|
||||
It creates one abandoned browse point and six abandoned history points through
|
||||
the same encrypted canonical fixture helpers. Before close, the retained server
|
||||
session has exactly `(1,6)` points; SDK2's stronger post-close `(0,0)` check remains.
|
||||
|
||||
The old authentication token returns exactly `BadSessionIdInvalid` (`0x80250000`).
|
||||
A fresh session rejects both old continuation tokens with
|
||||
`BadContinuationPointInvalid`; invalid history does not call the historian.
|
||||
Fresh reads and the session's own browse/history roundtrips succeed around the
|
||||
denials, so a generally broken channel cannot satisfy this control.
|
||||
|
||||
After the session helper and its completed async state machine leave the isolated
|
||||
boundary, **all 23 old client/session/point/value/state targets are collectible
|
||||
while the same server is still running**, in each of five fixed GC observations.
|
||||
After normal host/application disposal and the fixture boundary, all 13 observed
|
||||
application/configuration/manager/validation-core/store/server/node-manager/
|
||||
backend targets are collectible in every round. Independent retained/collectible
|
||||
observer controls behave as expected. Both SDK2 certificate managers are disposed,
|
||||
cached stores are empty and actual PKI descriptors are zero.
|
||||
|
||||
Earlier one-history-point control receipts remain recorded: `b5986c61` passed
|
||||
with the original two-status auth whitelist; `6737e367` passed after narrowing to
|
||||
the observed exact status. Six affected history tests also passed at `6737e367`.
|
||||
Their launcher mistakenly expected seven tests. The original false guard receipt
|
||||
is retained; a separate source inventory and TRX review confirms four session
|
||||
history tests plus two event-paging tests, all executed/passed. No seventh source
|
||||
test is missing and the tests were not rerun to correct that bookkeeping error.
|
||||
|
||||
[Machine-readable observations, commands and raw hashes](close-ownership-candidate.json)
|
||||
retain all four executions. The current build has zero warnings/errors. Astra
|
||||
reviewed the design and actual code before each diagnostic execution; it verified
|
||||
all three close-control TRX files, the aligned 23/13 weak-target result and the
|
||||
six-test inventory correction independently.
|
||||
|
||||
This establishes bounded candidate close semantics and managed collectibility.
|
||||
It does **not** establish full canonical operation/host parity with the original
|
||||
standalone adapter, a steady RSS denominator, a resource-budget waiver, macOS
|
||||
native-retention resolution or G4 acceptance. No production code changed.
|
||||
@@ -1,86 +0,0 @@
|
||||
# Updated SDK 2 / HistorianGateway 1.0.0 publish smoke — 2026-11-10
|
||||
|
||||
**Passed:** four fresh self-contained Host/CLI publishes, static RID/dependency inspection, and the actual Linux ARM64 Host two-start/stop runtime smoke on the updated HistorianGateway 1.0.0 graph. Windows runtime/service installation remains pending under #800. This report does not complete G4.
|
||||
|
||||
All four artifacts and the unchanged existing probe were built from SDK 2 source `f2a8ce13059b266e53448739a6be0a32732f58d5` in a clean isolated checkout. The only committed change in this lane is this report; no runner, production source, package policy, existing fleet, sibling repository or issue was changed. The original smoke runner from `3a11087b` was reused without edits.
|
||||
|
||||
## Published graph and artifacts
|
||||
|
||||
Build environment: .NET SDK **10.0.403**, self-contained runtime **10.0.14**. Every publish used Release, the explicit RID, `--self-contained true`, `PublishSingleFile=false`, `PublishTrimmed=false`, `-m:1`, fresh output and external task-owned `--artifacts-path` directories. Four application publishes and the probe publish exited **0**, with no build warning/error diagnostics. Publishing was sequential while the coordinator ran its separate test lane. No Native AOT was attempted.
|
||||
|
||||
Both actual Host publish trees contain `ZB.MOM.WW.HistorianGateway.Client/1.0.0` and `ZB.MOM.WW.HistorianGateway.Contracts/1.0.0` in their `.deps.json` package graphs. The shipped DLLs report assembly/file version **1.0.0.0** and informational version **1.0.0+ea9f21c850fb618767e12690924f9966f1e433ac**. Their bytes match the actual published-package proof in [the HG 131 results](../../../../scripts/validation/historiangw-131/RESULTS.md). CLI does not depend on the HistorianGateway packages; it was rebuilt from the same updated source graph.
|
||||
|
||||
| Shipped DLL, identical in Linux and Windows Host artifacts | SHA-256 |
|
||||
|---|---|
|
||||
| `ZB.MOM.WW.HistorianGateway.Client.dll` | `b89a02e0d228ec549c4dfb755694f7f67b573a6077f06ff2781165e884fc5e12` |
|
||||
| `ZB.MOM.WW.HistorianGateway.Contracts.dll` | `e60d3d4650be5d251982f7847404daf1b666f61d56e2b0ccb844af8677e97743` |
|
||||
|
||||
Every OPC Foundation package dependency is **2.0.1** and every inspected SDK assembly is **2.0.1.0**. Each SDK basename occurs once per application tree; there is no old SDK or analyzer runtime artifact. Assembly metadata was read without executing the assemblies, using `PEReader`/`MetadataReader`.
|
||||
|
||||
| Artifact | Files / bytes | SDK assemblies | Native entries |
|
||||
|---|---:|---:|---:|
|
||||
| linux-arm64/host | 1385 / 356614102 | 8 | 34 |
|
||||
| linux-arm64/cli | 236 / 111341043 | 7 | 16 |
|
||||
| win-x64/host | 1390 / 342187531 | 8 | 37 |
|
||||
| win-x64/cli | 236 / 103181233 | 7 | 16 |
|
||||
|
||||
All inspected Linux native entries are ELF64 AArch64; all Windows native entries are x86-64 PE. Apphosts and bundled runtime libraries match their RID. Runtimeconfig `includedFrameworks` records Microsoft.NETCore.App 10.0.14, plus Microsoft.AspNetCore.App 10.0.14 for Host. Both Host artifacts include the separately self-contained script worker; the smoke used the default in-process script runner and does not exercise out-of-process scripting.
|
||||
|
||||
| Artifact | Apphost SHA-256 | Full-file manifest SHA-256 |
|
||||
|---|---|---|
|
||||
| linux-arm64/host | `d97f318f268246852603166a19d66c2da788a75a7f9124b2242e6c794985dcbb` | `be1c2f45587950007863b38050d3b48e593a82ce156816369461ba072ebd4c27` |
|
||||
| linux-arm64/cli | `b4840db34c07ec7f0fa8cbc220c5552fac87527d3b222c4e47260c68c7eedb19` | `0441fe823afd7d69e1a100786ae4b988445f228b3028976bfddc411de8984b0d` |
|
||||
| win-x64/host | `bf247acd5446a5b2ded0f90dab2b33662f08e8623fb87bd1b752d1aff38671d7` | `72ef93087da85c0dac80535915a7541e3cf8044a740eac1391ebdc173718dbc0` |
|
||||
| win-x64/cli | `949efc2cd8e71638596c3ac37dd526558513d9b09a6777d546f1d207ee691e01` | `45611b8b71673d75b7bcb7484322c16bee36cb2efc4895ca6054421c31680531` |
|
||||
|
||||
Full fresh manifests are `linux-arm64-host-sha256.json`, `linux-arm64-cli-sha256.json`, `win-x64-host-sha256.json` and `win-x64-cli-sha256.json` in the evidence root below. They exclude runtime logs/private state. `publish-inventory.json`, `native-inventory.json` and `assembly-metadata.json` preserve versions, architecture, paths and hashes. Shared SDK assembly bytes agree across all artifacts that contain each module:
|
||||
|
||||
| SDK module, version 2.0.1.0 | SHA-256 |
|
||||
|---|---|
|
||||
| `Opc.Ua.Client` | `620da406fabdbc75d11f9827ea7e39d2d3c762471bd2264b0d11f1d6cd9247cd` |
|
||||
| `Opc.Ua.Configuration` | `6ed6a594c93c3ff35d1a16539a9fe87c1e2640549cc2f48ed6bae333dc8bf0e7` |
|
||||
| `Opc.Ua.Core` | `9d0857aa6b7f3c49037d4ea557b4da8edf07e146069464481783e66c5c9cd35a` |
|
||||
| `Opc.Ua.Core.Schema` | `51cfad48657d95d38074bb88be29aea6f5b361a07397247d58838d066b99772e` |
|
||||
| `Opc.Ua.Core.Types` | `a7dd141b8dabe8848ff28c2fb8e16a85a0508e6a49e6b1a1c1e267175b99af96` |
|
||||
| `Opc.Ua.Security.Certificates` | `7f4969aceb2f0db5328c6882cb4b117342f3b18905c38acdba600683860c4fd0` |
|
||||
| `Opc.Ua.Server` | `930e714a2f6e15d393840bcdc95e1afa8012bc740c3738a655f958142721864e` |
|
||||
| `Opc.Ua.Types` | `c542f69882f4e8a4ebd5ccc28a3881d6967c7ffb6dcc3c56dc6c776f39c2ede1` |
|
||||
|
||||
## Actual Linux Host runtime
|
||||
|
||||
The existing runner completed at **2026-11-10T19:47:49.570167+00:00**. Image: `mcr.microsoft.com/dotnet/sdk:10.0.103-noble`, immutable ID `sha256:b04611ee9e1b7d36797012ed921962c57189cb4dbb3dff12afb8e158110f293b`, digest `mcr.microsoft.com/dotnet/sdk@sha256:e362a8dbcd691522456da26a5198b8f3ca1d7641c95624fadc5e3e82678bd08a`, Linux arm64. The real published self-contained `OtOpcUa.Host` was the container entrypoint; the SDK image supplied only the probe framework.
|
||||
|
||||
The fixture used a fresh task-owned LocalDb/secret store and GUID application PKI, a single local Akka driver-role node, `FetchAndCache`, an unreachable loopback central endpoint, and a seeded deployment containing one raw folder and a real peppered HMAC API key. It used the production authentication and cache-restoration paths. All containers had `--network none`, no published host ports and task labels. The same application, state and PKI were started and stopped twice.
|
||||
|
||||
| Executed check | Result |
|
||||
|---|---|
|
||||
| Readiness/liveness/active health on each boot | Six requests passed; readiness/active Healthy, Akka Up |
|
||||
| Trusted peer, Basic256Sha256 SignAndEncrypt, real HMAC API key | Two Good reads; strict peer autoaccept false |
|
||||
| Wrong API-key secret | Two `BadIdentityTokenRejected` denials |
|
||||
| Untrusted server | `BadCertificateUntrusted` |
|
||||
| Untrusted client | `BadSecurityChecksFailed` |
|
||||
| Actual published CLI help and encrypted reads | Help exit 0; two Good ServerStatus.State reads, exit 0 |
|
||||
| Stop / restart / stop | Both stops exit 0, no OOM kill; served state restored on both boots |
|
||||
| Execution-count guards | Exactly two boots and six strict SDK cases; overall runtime exit 0 |
|
||||
|
||||
The CLI retains its existing autoaccept behavior and has no strict-validation flag. Its reads are separate from the strict SDK peer checks. The closed-port CLI preparation returned the expected nonzero status and was not counted as a successful connection. This smoke verifies the updated Host package contents and OPC UA startup/security paths; it does not call a HistorianGateway or live AVEVA backend.
|
||||
|
||||
Application DER SHA-256 on both boots: `7d8deca04ba8f73005c477f2aedde7a55ab3fecdba36faa49d57648e77bd254a`. Preserved thumbprint on both boots: `sha1 Fingerprint=4A:1D:8C:4F:22:01:F2:B7:7E:C0:99:92:54:24:8F:CC:AD:A9:E5:5E`. The certificate bytes were unchanged.
|
||||
|
||||
Raw application/probe stdout/stderr and appended rolling logs were scanned before redacted copies were saved. Task secret matches were **0** in raw and saved output; the appended Serilog selflog was **0 bytes**. The mode-0600 environment file was removed. Authentication/certificate denials remained diagnosable.
|
||||
|
||||
The task container `340ffd5844fe6d71b00cdc8dbbddfaf4bd109e420912264637c9b93728fee16d` was removed after its second clean stop. No matching smoke container remains and no existing fleet or store was modified.
|
||||
|
||||
## Evidence and reproduction
|
||||
|
||||
Evidence root: `/tmp/opcua2-publish-hg100-20261110`.
|
||||
Runtime logs, health responses, command exits and summary: `/tmp/opcua2-publish-hg100-20261110/runtime-c4244a56c29942e68f259a6522331632`.
|
||||
The exact six build/runtime invocations, source revision and exits are in `validation-receipt.json` (SHA-256 `2858beab92c3ef19df894c54886b4da97d27e734f980fc02dfe63f2246c885e7`). Runtime `summary.json` SHA-256: `bf81953127c4cd95ccbb6b4d2dbbf266cd8890ebbd667f2de0e588d9e0f89e7d`.
|
||||
|
||||
The four per-publish logs, `probe-publish.log`, `linux-runtime.log`, manifest files and inventory JSON files remain under the evidence root. The private state directory is not a distributable artifact. The read-only inventory helpers used for this run are retained at `/tmp/opcua2-publish-hg100-inventory.py` and `/tmp/opcua2-publish-hg100-metadata/`; application code was not loaded by these inspectors.
|
||||
|
||||
Reproduce using [the existing publish-smoke recipe](../../../../scripts/validation/opcua-publish-smoke/README.md), selecting a fresh task directory and adding `--artifacts-path "$task_output/build-$rid"` to the application publishes and `--artifacts-path "$task_output/build-probe"` to the probe publish. Exact commands for this completed run are in the receipt. No existing runner fix was required.
|
||||
|
||||
**Pending #800:** Windows service installation, account/ACL behavior and actual Windows two-start/stop runtime validation remain an operator gate on an approved environment. Cross-publishing and PE inspection do not satisfy that gate. No WinRM, psbridge, replacement remote-execution channel, Windows service action or deployment was used.
|
||||
|
||||
Backend/AVEVA interoperability, load/performance, failover and the existing server lifecycle/RSS findings remain separate gates. This publish smoke does not waive them.
|
||||
@@ -1,43 +0,0 @@
|
||||
# CI3 Runtime rebuild idempotence assertion investigation
|
||||
|
||||
Base: `04d5513af2620f277a56acbb19ae466623fc054f` (SDK2, actual HG1.0), branch `codex/opcua2-rebuild-test-barrier`. SDK `10.0.403`. No production edits, budget changes, expected result changes, skips, or issue actions.
|
||||
|
||||
## Cause and classification evidence
|
||||
|
||||
`RecordingSink.EnsureFolder` queues `EF:eq-1` before the actor finishes materialisation and calls `AnnounceAddedNodes`, which queues `NA:line-1`. The old test waited only for EF, captured a possibly incomplete first-call count, then slept after sending the second request. Thus it could attribute the first apply's trailing announcement to the second apply. `FinishRebuild` sends the public `RebuildCompleted` outcome after `CompleteAddressSpaceApply` and deferred writes, so it supplies the needed completion barrier.
|
||||
|
||||
An independent source comparison against landed SDK1.5 master `230cef4e` found no actor/test changes: `git diff 230cef4e 04d5513a -- src/Server/ZB.MOM.WW.OtOpcUa.Runtime/OpcUa/OpcUaPublishActor.cs tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/OpcUa/OpcUaPublishActorRebuildTests.cs` has zero bytes (`master-candidate-source.diff`). This supports a preexisting test-ordering failure, not an SDK2 production idempotence regression.
|
||||
|
||||
## Controlled reproduction
|
||||
|
||||
Temporary test-only `AfterEnsureFolder` gate blocked the first apply immediately after EF was recorded. The original EF-presence wait and snapshot therefore captured exactly one call. The second request was queued, the gate released, and both apply-completion counters awaited before the unchanged count assertion. The exact CI failure reproduced: expected 1, actual 2. Diagnostic records `completed calls=EF:eq-1,NA:line-1; completions=2`. There was only one EF and one announcement: no repeated materialisation.
|
||||
|
||||
- RED: `controlled-red/controlled-red-diagnostic.trx`, `test-diagnostic.log`, `controlled-red-source.cs`; build exit0, test exit1, guard exit0; 1 failed/0 passed/0 skipped (expected reproduction).
|
||||
- GREEN: same first-apply gate with explicit count1 while blocked; release, then await first correlated clean `RebuildCompleted` before snapshot and second correlated clean reply before assertion. `controlled-green/controlled-green.trx`, `controlled-green-source.cs`; build0/test0/guard0; 1 passed/0 failed/0 skipped.
|
||||
- Temporary gates are absent from final source. Only the target test changes: both requests ask for outcomes, both replies must match correlation and be clean, original EF/no-full-rebuild/unchanged-call-count assertions remain, and fixed sleep is removed. Existing `PresenceBudget` and cancellation token are retained.
|
||||
|
||||
## Reproduction commands
|
||||
|
||||
From the owned worktree, test project is `tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests/ZB.MOM.WW.OtOpcUa.Runtime.Tests.csproj`.
|
||||
|
||||
```sh
|
||||
dotnet build "$PROJECT" -c Release --no-restore
|
||||
dotnet test "$PROJECT" -c Release --no-build --no-restore --filter 'FullyQualifiedName~Second_rebuild_with_same_artifact_is_empty_plan_no_op' --logger 'trx;LogFileName=focused.trx' --results-directory "$RESULTS"
|
||||
# Preserve dotnet exit before guard; guard does not replace test status.
|
||||
MIN_EXECUTED=1 bash scripts/ci/assert-not-all-skipped.sh "$RESULTS/focused.trx"
|
||||
# Owning suite omits --filter and uses its own fresh results directory/TRX.
|
||||
```
|
||||
|
||||
## Final validation
|
||||
|
||||
Commit: `b5f51406ffc7dcf5b40baa52156ea85e862ab5b4` (one test file; worktree clean).
|
||||
|
||||
Final owning project build: exit0, 0 warnings, 0 errors, 2.97s (`final/build.log`, `final/build-status.txt`). Full unfiltered Runtime suite: 1,005 total, 1,002 passed, 0 failed, 3 existing skips, duration1m25s. Test exit0, nonzero execution guard exit0 (`final/runtime-final.trx`, `final/test.log`, `final/guard.log`, `final/status.txt`). Target test is passed in that full-suite TRX. DLL SHA256 is recorded in `final/runtime-dll.sha256`.
|
||||
|
||||
The three existing skips are the retired-v3 artifact/composer parity tests `Composer_and_artifact_agree_on_equipment_node_device_host`, `ParseComposition_scoped_flags_cross_cluster_orphan_equipment`, and `Driverbound_equipment_kept_when_driver_in_cluster`. No skips were added or changed. No remaining diagnostics from this work.
|
||||
|
||||
Host concurrently ran coordinator validation; this task makes no performance claim. Root owns broader CI/fixture classification and issue writes.
|
||||
|
||||
|
||||
|
||||
Coordinator landing: master `52d1373e`, merged into SDK2 at `75057d8c`; [#805](https://gitea.dohertylan.com/dohertj2/lmxopcua/issues/805) closed after independent SDK1.5 master Runtime validation:1,002passed/0failed/3existing skips, test/guard exits0. No product source changed. Fresh full CI4 follows this repair and fixture correction; it is not assumed green from the owning-suite pass.
|
||||
@@ -1,352 +0,0 @@
|
||||
{
|
||||
"scope": "Instrumented candidate-only canonical saturation diagnostic. No acceptance protocol or baseline change.",
|
||||
"allocationTracking": {
|
||||
"enabled": true,
|
||||
"environment": "OPCUA_CERTIFICATE_LEAK_TRACKING=1",
|
||||
"overhead": "Exact SDK captures a StackTrace and tracker entry per certificate wrapper. Not an uninstrumented performance/acceptance baseline."
|
||||
},
|
||||
"bundle": {
|
||||
"sourceRevision": "2738d7cc8675298ceb38ed19ca58a9f643036ff1",
|
||||
"receiptSha256": "e4eed693c80baa29266f58cee4473b1181bc6de8f4c460843bd6b1993bcf7179",
|
||||
"sdk": "2.0.1",
|
||||
"gateway": "1.0.0",
|
||||
"runtime": "self-contained Linux ARM64 10.0.14 for target and observer",
|
||||
"sha256": "e4eed693c80baa29266f58cee4473b1181bc6de8f4c460843bd6b1993bcf7179"
|
||||
},
|
||||
"run": {
|
||||
"acceptance": false,
|
||||
"containerExitStatus": 1,
|
||||
"wallSeconds": 1429.7275004169205,
|
||||
"sourceRevision": "2738d7cc8675298ceb38ed19ca58a9f643036ff1",
|
||||
"receiptSha256": "e4eed693c80baa29266f58cee4473b1181bc6de8f4c460843bd6b1993bcf7179",
|
||||
"descriptorTests": {
|
||||
"executed": 2,
|
||||
"skipped": 0
|
||||
},
|
||||
"experimentTests": {
|
||||
"executed": 1,
|
||||
"skipped": 0
|
||||
},
|
||||
"diagnosticOutcome": {
|
||||
"kind": "saturation-result",
|
||||
"utc": "2026-11-10T20:30:58.5817344+00:00",
|
||||
"canonicalCycles": 384,
|
||||
"settlingCycles": 1,
|
||||
"restarts": 96,
|
||||
"phaseSeconds": 1425.2416632,
|
||||
"readiness": true,
|
||||
"coldBudgetRejected": true,
|
||||
"shutdownOwnershipVerified": true,
|
||||
"acceptance": false
|
||||
},
|
||||
"protocolCompleted": true
|
||||
},
|
||||
"start": {
|
||||
"kind": "start",
|
||||
"utc": "2026-11-10T20:07:13.3303503+00:00",
|
||||
"processId": 200,
|
||||
"mode": "saturation",
|
||||
"requestedSeconds": 1800,
|
||||
"minimumFullSeconds": 7200,
|
||||
"build": "2738d7cc8675298ceb38ed19ca58a9f643036ff1",
|
||||
"sdk": "2.0.1+07e62f72500cc0923a2bab940653c8c1116fa286",
|
||||
"diagnosticInstrumentation": "SDK2.0.1 CP lists and certificate-validation cached stores; read-only",
|
||||
"limits": {
|
||||
"retainedManagedGrowthBytes": 67108864,
|
||||
"rssGrowthBytes": 134217728,
|
||||
"fdGrowth": 32
|
||||
},
|
||||
"coverage": "encrypted sessions; scalar/Int16[] Raw+UNS; subscription removal; browse abandonment; history release/cross-session/close; surgical changes/rebuild; revocation; paused TCP read/recovery; same-PKI restart"
|
||||
},
|
||||
"coldRejection": {
|
||||
"kind": "budget-rejected",
|
||||
"cycle": 248,
|
||||
"seconds": 913.8748808,
|
||||
"resources": {
|
||||
"Cycle": 248,
|
||||
"Seconds": 913.830416,
|
||||
"Sessions": 0,
|
||||
"Subscriptions": 0,
|
||||
"Items": 0,
|
||||
"BrowsePoints": 0,
|
||||
"HistoryPoints": 0,
|
||||
"LiveDataItems": 0,
|
||||
"LiveEventItems": 0,
|
||||
"MonitoredNodes": 0,
|
||||
"Variables": 19,
|
||||
"Folders": 4,
|
||||
"Conditions": 1,
|
||||
"CachedCertificateStores": 2,
|
||||
"Descriptors": 193,
|
||||
"PkiDescriptors": 0,
|
||||
"ManagedBytes": 19961096,
|
||||
"RssBytes": 362409984,
|
||||
"AllocatedBytes": 5662357112,
|
||||
"Gen0": 619,
|
||||
"Gen1": 496,
|
||||
"Gen2": 496,
|
||||
"GcCommittedBytes": 48226304,
|
||||
"GcHeapBytes": 22015464,
|
||||
"GcFragmentedBytes": 2054368,
|
||||
"PinnedObjects": 1,
|
||||
"PendingFinalizers": 17,
|
||||
"JitMethods": 75848,
|
||||
"JitIlBytes": 11437192,
|
||||
"ActiveTimers": 16,
|
||||
"Threads": 21
|
||||
},
|
||||
"baseline": {
|
||||
"Cycle": 3,
|
||||
"Seconds": 7.6451075,
|
||||
"Sessions": 0,
|
||||
"Subscriptions": 0,
|
||||
"Items": 0,
|
||||
"BrowsePoints": 0,
|
||||
"HistoryPoints": 0,
|
||||
"LiveDataItems": 0,
|
||||
"LiveEventItems": 0,
|
||||
"MonitoredNodes": 0,
|
||||
"Variables": 19,
|
||||
"Folders": 4,
|
||||
"Conditions": 1,
|
||||
"CachedCertificateStores": 2,
|
||||
"Descriptors": 191,
|
||||
"PkiDescriptors": 0,
|
||||
"ManagedBytes": 19878208,
|
||||
"RssBytes": 224620544,
|
||||
"AllocatedBytes": 86490920,
|
||||
"Gen0": 7,
|
||||
"Gen1": 6,
|
||||
"Gen2": 6,
|
||||
"GcCommittedBytes": 41967616,
|
||||
"GcHeapBytes": 20716064,
|
||||
"GcFragmentedBytes": 837856,
|
||||
"PinnedObjects": 1,
|
||||
"PendingFinalizers": 16,
|
||||
"JitMethods": 35741,
|
||||
"JitIlBytes": 4635402,
|
||||
"ActiveTimers": 18,
|
||||
"Threads": 27
|
||||
},
|
||||
"failure": "Shouldly.ShouldAssertException: 362409984L\r\n should be less than or equal to\r\n358838272L\r\n but was not\n at ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.Sdk2LifecycleSoakTests.Repeated_lifecycles_return_resources_to_a_steady_baseline() in tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/Sdk2LifecycleSoakTests.cs:line 133"
|
||||
},
|
||||
"observer": {
|
||||
"protocol": "sdk2-saturation-v1",
|
||||
"runId": "545b3093-5eab-4348-a72d-926b9d1da7da",
|
||||
"targetPid": 200,
|
||||
"observerPid": 109,
|
||||
"active": false,
|
||||
"drained": true,
|
||||
"markersValid": true,
|
||||
"eventsLost": 0,
|
||||
"sdkFactoryJit": 0,
|
||||
"sdkFactoryLoads": 0,
|
||||
"sdkAssemblyLoads": 0,
|
||||
"windows": [
|
||||
{
|
||||
"name": "window1",
|
||||
"firstCycle": 321,
|
||||
"lastCycle": 352,
|
||||
"startRestarts": 80,
|
||||
"endRestarts": 88,
|
||||
"sdkFactoryJit": 0,
|
||||
"sdkFactoryLoads": 0,
|
||||
"sdkAssemblyLoads": 0
|
||||
},
|
||||
{
|
||||
"name": "window2",
|
||||
"firstCycle": 353,
|
||||
"lastCycle": 384,
|
||||
"startRestarts": 88,
|
||||
"endRestarts": 96,
|
||||
"sdkFactoryJit": 0,
|
||||
"sdkFactoryLoads": 0,
|
||||
"sdkAssemblyLoads": 0
|
||||
}
|
||||
],
|
||||
"otherJit": 287,
|
||||
"loadedNativeBytes": 60760,
|
||||
"runtimeControlJit": 0,
|
||||
"configuration": {
|
||||
"runtimeProvider": "Microsoft-Windows-DotNETRuntime",
|
||||
"level": "Verbose",
|
||||
"keywords": "0x18",
|
||||
"markerProvider": "OtOpcUa-Sdk2-Saturation",
|
||||
"circularBufferMiB": 16,
|
||||
"requestRundown": false
|
||||
},
|
||||
"acceptance": false
|
||||
},
|
||||
"tests": {
|
||||
"descriptor-controls": {
|
||||
"counters": {
|
||||
"total": "2",
|
||||
"executed": "2",
|
||||
"passed": "2",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"sha256": "0de2cd05f9f1dbcaee3cff33e3e625723f5dc19b8f2dbcf3fbf1376792bc489c",
|
||||
"errors": []
|
||||
},
|
||||
"saturation": {
|
||||
"counters": {
|
||||
"total": "1",
|
||||
"executed": "1",
|
||||
"passed": "0",
|
||||
"failed": "1",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"sha256": "1b5cba9e1b3c348d0dcbb79ba4c715d0e837602c78afc2c221c64c2e776e825b",
|
||||
"errors": [
|
||||
"Shouldly.ShouldAssertException : 362409984L\r\n should be less than or equal to\r\n358838272L\r\n but was not"
|
||||
]
|
||||
}
|
||||
},
|
||||
"firstSample": {
|
||||
"Cycle": 1,
|
||||
"Seconds": 2.7631819,
|
||||
"Sessions": 0,
|
||||
"Subscriptions": 0,
|
||||
"Items": 0,
|
||||
"BrowsePoints": 0,
|
||||
"HistoryPoints": 0,
|
||||
"LiveDataItems": 0,
|
||||
"LiveEventItems": 0,
|
||||
"MonitoredNodes": 0,
|
||||
"Variables": 19,
|
||||
"Folders": 4,
|
||||
"Conditions": 1,
|
||||
"CachedCertificateStores": 2,
|
||||
"Descriptors": 191,
|
||||
"PkiDescriptors": 0,
|
||||
"ManagedBytes": 19275376,
|
||||
"RssBytes": 222228480,
|
||||
"AllocatedBytes": 62054576,
|
||||
"Gen0": 3,
|
||||
"Gen1": 2,
|
||||
"Gen2": 2,
|
||||
"GcCommittedBytes": 47521792,
|
||||
"GcHeapBytes": 20204744,
|
||||
"GcFragmentedBytes": 929368,
|
||||
"PinnedObjects": 1,
|
||||
"PendingFinalizers": 19,
|
||||
"JitMethods": 29401,
|
||||
"JitIlBytes": 4142214,
|
||||
"ActiveTimers": 12,
|
||||
"Threads": 27
|
||||
},
|
||||
"baselineSample": {
|
||||
"Cycle": 3,
|
||||
"Seconds": 7.6451075,
|
||||
"Sessions": 0,
|
||||
"Subscriptions": 0,
|
||||
"Items": 0,
|
||||
"BrowsePoints": 0,
|
||||
"HistoryPoints": 0,
|
||||
"LiveDataItems": 0,
|
||||
"LiveEventItems": 0,
|
||||
"MonitoredNodes": 0,
|
||||
"Variables": 19,
|
||||
"Folders": 4,
|
||||
"Conditions": 1,
|
||||
"CachedCertificateStores": 2,
|
||||
"Descriptors": 191,
|
||||
"PkiDescriptors": 0,
|
||||
"ManagedBytes": 19878208,
|
||||
"RssBytes": 224620544,
|
||||
"AllocatedBytes": 86490920,
|
||||
"Gen0": 7,
|
||||
"Gen1": 6,
|
||||
"Gen2": 6,
|
||||
"GcCommittedBytes": 41967616,
|
||||
"GcHeapBytes": 20716064,
|
||||
"GcFragmentedBytes": 837856,
|
||||
"PinnedObjects": 1,
|
||||
"PendingFinalizers": 16,
|
||||
"JitMethods": 35741,
|
||||
"JitIlBytes": 4635402,
|
||||
"ActiveTimers": 18,
|
||||
"Threads": 27
|
||||
},
|
||||
"lastSample": {
|
||||
"Cycle": 385,
|
||||
"Seconds": 1425.221077,
|
||||
"Sessions": 0,
|
||||
"Subscriptions": 0,
|
||||
"Items": 0,
|
||||
"BrowsePoints": 0,
|
||||
"HistoryPoints": 0,
|
||||
"LiveDataItems": 0,
|
||||
"LiveEventItems": 0,
|
||||
"MonitoredNodes": 0,
|
||||
"Variables": 19,
|
||||
"Folders": 4,
|
||||
"Conditions": 1,
|
||||
"CachedCertificateStores": 2,
|
||||
"Descriptors": 200,
|
||||
"PkiDescriptors": 0,
|
||||
"ManagedBytes": 19974280,
|
||||
"RssBytes": 367771648,
|
||||
"AllocatedBytes": 8790684304,
|
||||
"Gen0": 963,
|
||||
"Gen1": 770,
|
||||
"Gen2": 770,
|
||||
"GcCommittedBytes": 46555136,
|
||||
"GcHeapBytes": 20348120,
|
||||
"GcFragmentedBytes": 373840,
|
||||
"PinnedObjects": 1,
|
||||
"PendingFinalizers": 27,
|
||||
"JitMethods": 80193,
|
||||
"JitIlBytes": 12208985,
|
||||
"ActiveTimers": 15,
|
||||
"Threads": 22
|
||||
},
|
||||
"peakResources": {
|
||||
"ManagedBytes": 20501376,
|
||||
"RssBytes": 394956800,
|
||||
"Descriptors": 201,
|
||||
"PkiDescriptors": 0,
|
||||
"JitMethods": 80193,
|
||||
"GcCommittedBytes": 48549888
|
||||
},
|
||||
"evidenceSha256": {
|
||||
"run-receipt.json": "842eacf845af019df087c69c55bb527d83c6e0d6f42057c8dd63d65eb5f86511",
|
||||
"resources.jsonl": "eab640b684908d6978ca323c919d40b8ec6496a483484e3f86a396511e28dbc3",
|
||||
"control/drained.json": "5a61b090086f379f3cc96b1efe328225efdafb027795a57f7636acfbf2bc5594",
|
||||
"results/descriptor-controls.trx": "0de2cd05f9f1dbcaee3cff33e3e625723f5dc19b8f2dbcf3fbf1376792bc489c",
|
||||
"results/saturation.trx": "1b5cba9e1b3c348d0dcbb79ba4c715d0e837602c78afc2c221c64c2e776e825b",
|
||||
"test-exit-status.txt": "4355a46b19d348dc2f57c046f8ef63d4538ebb936000f3c9ee954a27460dd865",
|
||||
"observer-exit-status.txt": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa",
|
||||
"target-runtime.txt": "1287d31fb4a49b24e82c346e2b9d2a4ef956d151e08f0497c3aef78617d2a012",
|
||||
"observer-runtime.txt": "38c764d4f77a4bfa9c27905c5f8feb1076d30ea626f28d0f188e4bf86bb0c456"
|
||||
},
|
||||
"noOrdinaryCompleteRecord": true,
|
||||
"privatePkiAndRawTraceExcluded": true,
|
||||
"sanitization": {
|
||||
"checkoutPrefixRedacted": true,
|
||||
"rawResourceHashPreserved": true
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
# Candidate canonical saturation diagnostic
|
||||
|
||||
The prospectively fixed experiment completed 384 canonical cycles / 96 restarts
|
||||
plus one settling cycle in **1,425.242 seconds**, within the 1,800-second cutoff.
|
||||
Both traced windows, 321–352 and 353–384, recorded **zero generated-factory JIT/load
|
||||
events, zero new SDK assembly loads and zero lost events**; the continuous attached
|
||||
interval also had zero such events. Other JIT starts: 287. Summed CLR `MethodSize`
|
||||
values: 60,760 bytes; this is not an RSS/PSS measurement. The observer was active
|
||||
before cycle 321 and stopped/drained before cycle 385. Shutdown ownership checks
|
||||
passed.
|
||||
|
||||
**The cold resource failure remains:** cycle 248 RSS 362,409,984 exceeded
|
||||
358,838,272 bytes (cycle 3 + 128 MiB). The first assertion was retained and rethrown;
|
||||
test/container/launcher exit 1, one failed executed lifecycle test, no ordinary
|
||||
completion/full-duration result. Descriptor controls passed 2/2. Readiness=true
|
||||
describes the selected generated-factory criterion on the canonical workload,
|
||||
**not general runtime/performance readiness, G4 acceptance or #799 closure**.
|
||||
|
||||
Source `2738d7cc`, exact SDK 2.0.1 and HG 1.0.0; both participants use self-contained
|
||||
Linux ARM64 runtime 10.0.14. Astra approved the exact immutable 1,275-file bundle
|
||||
before launch and independently verified 1,064 module identities. The production/
|
||||
central-package source tree matched the candidate. Outer output permissions were
|
||||
0700; private PKI and raw trace stay unversioned.
|
||||
|
||||
`OPCUA_CERTIFICATE_LEAK_TRACKING=1` was enabled before startup. Exact SDK tracking
|
||||
captures an allocation StackTrace and tracker entry per wrapper. This additional
|
||||
diagnostic overhead prevents reuse as an uninstrumented performance/acceptance
|
||||
baseline. Caps and measurement baseline were unchanged.
|
||||
|
||||
[Hashed result, windows, failure and runtime receipts](saturation-candidate.json)
|
||||
preserve cold/warm/peak observations. A matched original-SDK canonical adapter,
|
||||
prospectively reviewed acceptance procedure and at least 7,200 seconds after fixed
|
||||
warmup are still required before a replacement resource gate could be considered.
|
||||
Continued macOS native certificate-object accumulation remains separate and
|
||||
unresolved. No production workaround or acceptance waiver was applied.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,349 +0,0 @@
|
||||
{
|
||||
"issue": 807,
|
||||
"scope": "SDK1 host terminal-disposal repair; independent of SDK2 migration release acceptance.",
|
||||
"originalMaster": "52d1373e8129b7f4f0ea2e35f86a8a5d0ed1de36",
|
||||
"redSource": "84bfe6cd20285ccf136998998ef5c051917d8201",
|
||||
"greenSource": "10edc44f94afc42300518f1504091c58217a89a9",
|
||||
"redProductionEqualsOriginalMaster": true,
|
||||
"redOriginalProductionSha256": "346362c8c18b5bcdb90757f654c02c68bad44fc5875abc8b4672f4c7ac49b381",
|
||||
"greenProductionSha256": "c4934b15e695a4110e8cea8fbdef8faabad80aadeca4ccfb007b11400057ff9b",
|
||||
"resolvedSdkPackages": [
|
||||
"OPCFoundation.NetStandard.Opc.Ua.Configuration/1.5.378.182",
|
||||
"OPCFoundation.NetStandard.Opc.Ua.Core/1.5.378.182",
|
||||
"OPCFoundation.NetStandard.Opc.Ua.Security.Certificates/1.5.378.182",
|
||||
"OPCFoundation.NetStandard.Opc.Ua.Server/1.5.378.182",
|
||||
"OPCFoundation.NetStandard.Opc.Ua.Types/1.5.378.182"
|
||||
],
|
||||
"builds": [
|
||||
{
|
||||
"rawLogPath": "/tmp/opcua-sdk1-terminal-red-build.log",
|
||||
"sha256": "38f5561a0db2a2d26f8462f36e114ced057c189effcd6e87dc5a62a42c06d52e",
|
||||
"warnings": 0,
|
||||
"errors": 0
|
||||
},
|
||||
{
|
||||
"rawLogPath": "/tmp/opcua-sdk1-terminal-green-build.log",
|
||||
"sha256": "5fae318d45d9b5b8b4ba2812ef87869edf6d851e09848154d5f4a51f47ed68d2",
|
||||
"warnings": 0,
|
||||
"errors": 0
|
||||
},
|
||||
{
|
||||
"rawLogPath": "/tmp/opcua-sdk1-terminal-solution-build.log",
|
||||
"sha256": "13317ee89238730216874531fad82e3591a6d0d1b5503c8bd896dcc95c885daf",
|
||||
"warnings": 0,
|
||||
"errors": 0
|
||||
}
|
||||
],
|
||||
"runs": [
|
||||
{
|
||||
"source": "84bfe6cd20285ccf136998998ef5c051917d8201",
|
||||
"rawDirectory": "artifacts/opcua2/84bfe6cd/sdk1-terminal-red",
|
||||
"command": [
|
||||
"dotnet",
|
||||
"test",
|
||||
"tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"--no-build",
|
||||
"--no-restore",
|
||||
"--filter",
|
||||
"FullyQualifiedName~OpcUaApplicationHostDisposalTests",
|
||||
"--logger",
|
||||
"trx;LogFileName=close.trx",
|
||||
"--results-directory",
|
||||
"artifacts/opcua2/84bfe6cd/sdk1-terminal-red"
|
||||
],
|
||||
"testExit": 1,
|
||||
"guardPassed": true,
|
||||
"runnerSeconds": 3.8918902919394895,
|
||||
"counters": {
|
||||
"total": "5",
|
||||
"executed": "5",
|
||||
"passed": "0",
|
||||
"failed": "5",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"selectedResults": [
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Host_terminally_disposes_its_booted_server_once",
|
||||
"outcome": "Failed",
|
||||
"error": "Shouldly.ShouldAssertException : server.TerminalDisposals\r\n should be\r\n1\r\n but was\r\n0"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Concurrent_disposers_share_completion_and_one_cleanup_owner",
|
||||
"outcome": "Failed",
|
||||
"error": "Shouldly.ShouldAssertException : server.StopCalls\r\n should be\r\n1\r\n but was\r\n4"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Disposed_host_rejects_start_without_taking_server_ownership",
|
||||
"outcome": "Failed",
|
||||
"error": "Shouldly.ShouldAssertException : Task `host.StartAsync(server, Ct)`\r\n should throw\r\nSystem.ObjectDisposedException\r\n but did not"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Stop_failure_still_terminally_disposes_the_server",
|
||||
"outcome": "Failed",
|
||||
"error": "Shouldly.ShouldAssertException : server.TerminalDisposals\r\n should be\r\n1\r\n but was\r\n0"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Partial_startup_failure_does_not_strand_the_server",
|
||||
"outcome": "Failed",
|
||||
"error": "Shouldly.ShouldAssertException : server.TerminalDisposals\r\n should be\r\n1\r\n but was\r\n0"
|
||||
}
|
||||
],
|
||||
"rawHashes": {
|
||||
"close.trx": "ec832633adf184a07f31075ff342bb2c1b9d3f3893c518f5737dc02526f886bb",
|
||||
"run.log": "cdb7c4982d45807de53f70dfc22fad69ccda1db740db05407cef8df8b6b6d904",
|
||||
"receipt.json": "4469c071c0d178446ccfdbdca4bf11ebad43c33feb91d8a8c5f2fa891579f2dc"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": "10edc44f94afc42300518f1504091c58217a89a9",
|
||||
"rawDirectory": "artifacts/opcua2/10edc44f/sdk1-terminal-green",
|
||||
"command": [
|
||||
"dotnet",
|
||||
"test",
|
||||
"tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"--no-build",
|
||||
"--no-restore",
|
||||
"--filter",
|
||||
"FullyQualifiedName~OpcUaApplicationHostDisposalTests",
|
||||
"--logger",
|
||||
"trx;LogFileName=close.trx",
|
||||
"--results-directory",
|
||||
"artifacts/opcua2/10edc44f/sdk1-terminal-green"
|
||||
],
|
||||
"testExit": 0,
|
||||
"guardPassed": true,
|
||||
"runnerSeconds": 3.336757709039375,
|
||||
"counters": {
|
||||
"total": "5",
|
||||
"executed": "5",
|
||||
"passed": "5",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"selectedResults": [
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Partial_startup_failure_does_not_strand_the_server",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Concurrent_disposers_share_completion_and_one_cleanup_owner",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Host_terminally_disposes_its_booted_server_once",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Stop_failure_still_terminally_disposes_the_server",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Disposed_host_rejects_start_without_taking_server_ownership",
|
||||
"outcome": "Passed"
|
||||
}
|
||||
],
|
||||
"rawHashes": {
|
||||
"close.trx": "c44ba287659af567fcba1209c147aa5bfb6f2fc27753c0923d08b92372c007b4",
|
||||
"run.log": "7f68723461a5ac4154c247b8bdfcc6d3770a5c1c1a88016051ef492f1684c88e",
|
||||
"receipt.json": "bea02609e11dcc4569a26add9ae5836b101bf107d0346dd34514fc1d114ba525"
|
||||
}
|
||||
},
|
||||
{
|
||||
"source": "10edc44f94afc42300518f1504091c58217a89a9",
|
||||
"rawDirectory": "artifacts/opcua2/10edc44f/sdk1-server-suite",
|
||||
"command": [
|
||||
"dotnet",
|
||||
"test",
|
||||
"tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.csproj",
|
||||
"-c",
|
||||
"Release",
|
||||
"--no-build",
|
||||
"--no-restore",
|
||||
"--logger",
|
||||
"trx;LogFileName=close.trx",
|
||||
"--results-directory",
|
||||
"artifacts/opcua2/10edc44f/sdk1-server-suite"
|
||||
],
|
||||
"testExit": 0,
|
||||
"guardPassed": true,
|
||||
"runnerSeconds": 119.36682745895814,
|
||||
"counters": {
|
||||
"total": "1033",
|
||||
"executed": "1032",
|
||||
"passed": "1032",
|
||||
"failed": "0",
|
||||
"error": "0",
|
||||
"timeout": "0",
|
||||
"aborted": "0",
|
||||
"inconclusive": "0",
|
||||
"passedButRunAborted": "0",
|
||||
"notRunnable": "0",
|
||||
"notExecuted": "0",
|
||||
"disconnected": "0",
|
||||
"warning": "0",
|
||||
"completed": "0",
|
||||
"inProgress": "0",
|
||||
"pending": "0"
|
||||
},
|
||||
"selectedResults": [
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.AddressSpaceComposerDeviceHostTests.Compose_resolves_driver_device_and_device_host",
|
||||
"outcome": "NotExecuted",
|
||||
"error": "v3: equipment no longer binds a driver/device \u2014 Equipment lost DriverInstanceId/DeviceId and Compose no longer takes a devices list, so EquipmentNode's DriverInstanceId/DeviceId/DeviceHost projection is always null. Equipment references raw tags via UnsTagReference. The device-endpoint merge this suite characterized now lives in Runtime.Tests DeploymentArtifactRawPathTests; the host-extraction unit is Commons.Tests DeviceConfigIntentTests."
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Host_terminally_disposes_its_booted_server_once",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.BuildSecurityPolicies_empty_input_falls_back_to_none",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostTests.StartAsync_creates_application_certificate_in_pki_own",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostQuotaTests.Configured_transport_quotas_replace_only_what_is_set",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.BuildSecurityPolicies_default_set_emits_all_three_baseline_profiles",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Partial_startup_failure_does_not_strand_the_server",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.BuildUserTokenPolicies_withholds_anonymous_when_disallowed",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.NullOpcUaUserAuthenticator_always_denies",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostQuotaTests.Configured_request_quotas_are_applied",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_anonymous_token_is_rejected_when_disallowed",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_username_success_sets_identity_and_no_validation_error",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Disposed_host_rejects_start_without_taking_server_ownership",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostServerArrayTests.ServerArray_contains_local_uri_and_configured_peers_after_start",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostQuotaTests.Default_request_quotas_are_the_former_hard_coded_values",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.StartAsync_with_only_signandencrypt_omits_None_endpoint",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Concurrent_disposers_share_completion_and_one_cleanup_owner",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostQuotaTests.Unset_transport_quotas_keep_the_sdk_defaults",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostDisposalTests.Stop_failure_still_terminally_disposes_the_server",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_anonymous_token_is_admitted_with_a_role_carrying_identity",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.StartAsync_populates_ServerConfiguration_with_all_enabled_profiles",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostTests.StartAsync_reuses_existing_certificate_on_second_boot",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_username_denial_sets_validation_error_and_no_identity",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostQuotaTests.History_read_batch_cap_default_scales_with_the_machine",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.BuildSecurityPolicies_dedupes_repeated_profiles",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_authenticator_throwing_results_in_rejection",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_null_username_treated_as_empty_string",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostImpersonationTests.HandleImpersonation_username_success_carries_roles_on_identity",
|
||||
"outcome": "Passed"
|
||||
},
|
||||
{
|
||||
"name": "ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests.OpcUaApplicationHostSecurityTests.BuildUserTokenPolicies_emits_anonymous_and_username",
|
||||
"outcome": "Passed"
|
||||
}
|
||||
],
|
||||
"rawHashes": {
|
||||
"close.trx": "800ac4134f48fc901da2c3519573184337c3f9a22cc5e7a5f4859a6b586fbf70",
|
||||
"run.log": "253457c47f8801d37ce5fafc5c95cb9f5f0a9bbcead363c4ad0f5256e18fc7df",
|
||||
"receipt.json": "b0db91f846ca883c8b8d48a946021f5e99785a26c37ff1087187b83575f62c96"
|
||||
}
|
||||
}
|
||||
],
|
||||
"existingSkip": "AddressSpaceComposerDeviceHostTests.Compose_resolves_driver_device_and_device_host",
|
||||
"newSkips": 0,
|
||||
"ownership": "One caller owns detach/Stop/terminal Dispose; all Dispose callers await shared completion; Start after disposal begins is rejected.",
|
||||
"limits": [
|
||||
"Does not serialize an already-running asynchronous Start against Dispose.",
|
||||
"Does not alter immutable83ed880e baseline publications or aggregate regression oracles.",
|
||||
"Does not establish any relative RSS denominator, #799 acceptance or SDK2 release approval."
|
||||
],
|
||||
"review": "Astra approved the isolated SDK1 source/result/package gate: byte-identical original production RED; five expected REDs and five GREENs; 1032 owning-suite passes with one existing skip; all build hashes and selected security/PKI results verified. No SDK2 release or performance-baseline approval."
|
||||
}
|
||||
@@ -1,17 +1,8 @@
|
||||
**Landed:** OtOpcUa master `230cef4e` consumes the published Client/Contracts1.0.0;
|
||||
historiangw#131 is closed with verification. The change is merged into this SDK2
|
||||
branch. The patch below is a historical/replay input; the validator recognizes
|
||||
an already migrated checkout. [Master verification](../../../docs/plans/evidence/2026-11-10-historiangw-131.json)
|
||||
records the whole-solution zero-warning build,523 Gateway passes,1,002 Runtime
|
||||
passes and package hashes. SDK2 resource/release gates remain separate.
|
||||
|
||||
# HistorianGateway consumer TLS migration — issue 131
|
||||
|
||||
`consumer-1.0.0.patch` is a reviewable consumer change, kept separate from the
|
||||
buildable application in this checkout. Real paired Client/Contracts 1.0.0
|
||||
packages are now published and the isolated owning-project proof passed (RESULTS.md).
|
||||
The application in this checkout remains pinned to published 0.4.0 until the patch
|
||||
is applied by the coordinator.
|
||||
`consumer-1.0.0.patch` is a future consumer change, kept separate from the buildable
|
||||
application while the paired Client/Contracts 1.0.0 packages are being released.
|
||||
The application in this checkout remains pinned to published 0.4.0.
|
||||
|
||||
The patch changes both central package pins to 1.0.0 and maps the new option as:
|
||||
|
||||
@@ -43,17 +34,10 @@ package release. At initial inspection, both feed indexes listed exactly
|
||||
git apply --check scripts/validation/historiangw-131/consumer-1.0.0.patch
|
||||
git apply scripts/validation/historiangw-131/consumer-1.0.0.patch
|
||||
# From the consumer checkout, using a fresh run/results directory:
|
||||
hg131_results=/absolute/fresh/results
|
||||
test ! -e "$hg131_results" || exit 2
|
||||
mkdir -p "$hg131_results" || exit
|
||||
hg131_test_status=0
|
||||
dotnet test tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests \
|
||||
-c Release --logger trx --results-directory "$hg131_results" || hg131_test_status=$?
|
||||
hg131_guard_status=0
|
||||
MIN_EXECUTED=1 bash scripts/ci/assert-not-all-skipped.sh "$hg131_results"/*.trx \
|
||||
|| hg131_guard_status=$?
|
||||
if [ "$hg131_test_status" -ne 0 ]; then exit "$hg131_test_status"; fi
|
||||
exit "$hg131_guard_status"
|
||||
-c Release --logger trx --results-directory /absolute/fresh/results
|
||||
# Preserve dotnet test's exit; run the repository execution-count guard separately.
|
||||
MIN_EXECUTED=1 bash scripts/ci/assert-not-all-skipped.sh /absolute/fresh/results/*.trx
|
||||
```
|
||||
|
||||
Published-package verification must use the real 1.0.0 packages, preserve all test
|
||||
@@ -61,24 +45,12 @@ and guard exits, run the full owning project, and complete the consumer solution
|
||||
build/review before issue 131 is closed. The patch is transport-only and can be
|
||||
applied independently of the OPC UA SDK 2 rollout.
|
||||
|
||||
For isolated validation, use a fresh output directory OUTSIDE both repositories
|
||||
so the archived HG projects do not inherit the consumer's central package policy:
|
||||
|
||||
```bash
|
||||
python3 scripts/validation/historiangw-131/validate.py \
|
||||
--consumer-root "$PWD" \
|
||||
--hg-root /Users/dohertj2/Desktop/HistorianGateway \
|
||||
--output /tmp/historiangw-131-fresh-validation
|
||||
```
|
||||
|
||||
The script checks both live feed indexes. If both actual stable 1.0.0 packages are
|
||||
available, it validates them in an archived consumer copy. Otherwise it archives
|
||||
exact HG commit e432191 and temporarily replaces ONLY the archived Gateway csproj's
|
||||
two package references with source project references. This equivalent source
|
||||
validation does not create or publish any fake package/version. Restore uses an
|
||||
independent copy-on-write/copy cache, isolated HTTP cache and CLI home. Neither
|
||||
user checkout is built or edited. Full owning-suite TRX, required TLS failure
|
||||
classification, command exits and execution guard are retained under the task
|
||||
output. Published mode additionally checks package assets/provenance, absence of
|
||||
source overrides, and exact package-to-test-bin DLL hashes. Never treat source
|
||||
validation as stable published-package verification.
|
||||
If release availability lags, validate only in an archived staging copy: materialize
|
||||
exact HG commit e432191 with `git archive`, pack both packages with the local-only
|
||||
version `1.0.0-validation.131`, set an isolated `NUGET_PACKAGES`, and map only those
|
||||
two package IDs to a task-local feed. Apply the future patch to a separate consumer
|
||||
archive, then replace ONLY its two package pins with the validation prerelease.
|
||||
Never pack/build the user's HG checkout, publish these validation packages, place
|
||||
them in the normal NuGet cache, or pass prerelease validation off as stable-release
|
||||
verification. Local validation and release availability results are recorded in
|
||||
`RESULTS.md` when the run completes.
|
||||
|
||||
@@ -1,98 +1,13 @@
|
||||
# HG issue 131 — actual published 1.0.0 verification
|
||||
# Validation status
|
||||
|
||||
Both real stable **Client 1.0.0** and **Contracts 1.0.0** were observed in the live
|
||||
Gitea indexes at 2026-11-10 19:35:54 UTC and restored into a fresh isolated cache.
|
||||
The future consumer patch was applied only to a separate SDK 2 consumer archive.
|
||||
Application files in this working branch remain on 0.4.0, unchanged.
|
||||
Preparation only: future patch passes `git apply --check` in the SDK 2 candidate
|
||||
checkout. Published Client/Contracts 1.0.0 package verification is pending.
|
||||
|
||||
- Full Gateway owning project: **529 total, 523 passed, 0 failed, 6 existing live skips**.
|
||||
- Restore, test and repository execution-count guard exits: **0 / 0 / 0**.
|
||||
- All **3 real TLS/h2c wire cases passed** against the published packages.
|
||||
- Strict default rejected with AuthenticationException **UntrustedRoot**, before RPC.
|
||||
- Explicit opt-out and plaintext/stale-TLS-settings cases each completed one RPC.
|
||||
- Both assets entries are **type=package, version=1.0.0**, from the actual Gitea
|
||||
source. No source ProjectReference override: the archived Gateway csproj is
|
||||
byte-identical to the normal consumer csproj.
|
||||
- The only package folder is the task-isolated cache. Both copied test-bin DLL
|
||||
hashes equal the package DLL hashes. No package was packed or published here.
|
||||
Initial primary feed query returned versions 0.4.0, 0.3.0, 0.2.0, 0.1.0 for both
|
||||
packages. HG e4321915ebc5e0704a68ecad21b85c1cc1c80d6b contains the new option under
|
||||
Unreleased; both source package version declarations still read 0.4.0. The cached
|
||||
published Client 0.4.0 exposes RequireCertificateValidation and does not expose the
|
||||
new property. Current consumer files remain on 0.4.0 and unchanged.
|
||||
|
||||
Actual package RepositoryCommit for BOTH packages:
|
||||
`ea9f21c850fb618767e12690924f9966f1e433ac`.
|
||||
Consumer archive base: `4ea379fa92e571492ff9f49889a5eb91e3ad1e1a`.
|
||||
Applied patch SHA-256: `9452ee82b2bace7828a384b9f6048e9c931e8b4ec2078e0ee1baa175d0652fac`.
|
||||
|
||||
| Package | NuGet package SHA-256 | Consumed DLL SHA-256 |
|
||||
|---|---|---|
|
||||
| ZB.MOM.WW.HistorianGateway.Client 1.0.0 | `0a3f2836727671c07c0c393e705cc9737d2ed44258213a51fb4acf0d0ab7129e` | `b89a02e0d228ec549c4dfb755694f7f67b573a6077f06ff2781165e884fc5e12` |
|
||||
| ZB.MOM.WW.HistorianGateway.Contracts 1.0.0 | `83ffd12bcbbf919c973ba522560e10aa93a4cb8c686a3232030a2cfa5f00995e` | `e60d3d4650be5d251982f7847404daf1b666f61d56e2b0ccb844af8677e97743` |
|
||||
|
||||
Proof metadata/source/hash/readback checks:
|
||||
`/tmp/historiangw-131-published-20261110T193638Z/published-package-proof.json`.
|
||||
Full run metadata (including typed TLS error and package readback):
|
||||
`/tmp/historiangw-131-published-20261110T193638Z/metadata.json`.
|
||||
Fresh actual-package TRX: `/tmp/historiangw-131-published-20261110T193638Z/test-results`.
|
||||
Restore/test/guard logs: `/tmp/historiangw-131-published-20261110T193638Z`.
|
||||
|
||||
This completes the isolated SDK 2 owning-project proof. The coordinator separately
|
||||
owns the consumer-master full solution build, Astra review, landing/push and issue
|
||||
131 comment/closure. No issue action, package publication, or HG user-checkout
|
||||
mutation was performed by this validation lane. The live AVEVA fixture skips do
|
||||
not substitute for the three executed local wire tests.
|
||||
|
||||
---
|
||||
|
||||
# Earlier archived-source validation
|
||||
|
||||
Future consumer patch validated against exact archived HG source commit
|
||||
`e4321915ebc5e0704a68ecad21b85c1cc1c80d6b`. Consumer archive base:
|
||||
`18c22cf7eb042126226e540d9b979907328055c3`. Patch SHA-256:
|
||||
`9452ee82b2bace7828a384b9f6048e9c931e8b4ec2078e0ee1baa175d0652fac`.
|
||||
|
||||
## Scope and isolation
|
||||
|
||||
Mode: **unreleased source project references**, not published-package verification.
|
||||
At that earlier source-validation time, both feed indexes still listed only
|
||||
0.4.0, 0.3.0, 0.2.0, 0.1.0. The published-package run below supersedes that pending
|
||||
release-availability status.
|
||||
|
||||
The user's HG checkout was only read by git archive. Only the disposable archived
|
||||
consumer Gateway csproj had its two package references replaced by project
|
||||
references into the exact archived HG source. No package was packed or published;
|
||||
no fake 1.0.0 was inserted into any feed/cache. Restore used an independent copied
|
||||
NuGet cache, isolated HTTP cache and CLI home. The normal consumer files remain
|
||||
on published 0.4.0.
|
||||
|
||||
## Actual execution
|
||||
|
||||
- Full Gateway owning project: **529 total, 523 passed, 0 failed, 6 existing live skips**.
|
||||
- Test exit **0**; repository nonzero-execution guard exit **0**.
|
||||
- All three new local wire tests passed; no new skip or expected application-result change.
|
||||
- Strict default: base HistorianGatewayException -> RpcException Status Internal ->
|
||||
HttpRequestException -> AuthenticationException, certificate-chain **UntrustedRoot**.
|
||||
The test explicitly requires the typed TLS authentication failure; RPC calls = **0**.
|
||||
- Explicit TLS opt-out: actual metadata RPC succeeds; calls = **1**.
|
||||
- Plaintext with stale opt-out and nonexistent CA path: actual metadata RPC succeeds;
|
||||
calls = **1**.
|
||||
|
||||
The first source run compiled and executed but failed one new assertion because
|
||||
it predicted the narrower HistorianGatewayUnavailableException type. The actual
|
||||
TLS exception is the public base HistorianGatewayException; the corrected assertion
|
||||
retains the required AuthenticationException graph and zero-RPC check. The fresh
|
||||
second unfiltered run above passed. The six skipped cases are the existing AVEVA
|
||||
live fixture tests; they are not a substitute for TLS wire coverage.
|
||||
|
||||
Completed UTC: `2026-11-10T19:33:17.272468+00:00`.
|
||||
Actual metadata, typed TLS exception output and binary hashes:
|
||||
`/tmp/historiangw-131-validation-20261110T193106Z/metadata-final.json`.
|
||||
Fresh second-run TRX: `/tmp/historiangw-131-validation-20261110T193106Z/test-results2`.
|
||||
Test log: `/tmp/historiangw-131-validation-20261110T193106Z/test2.log`.
|
||||
Initial failed run and restore logs are retained in the same task directory.
|
||||
|
||||
Archived-source Client DLL SHA-256:
|
||||
`87e995a43c63debdd8f648a8feb8d19d9110b45eb7b2b6906159077d90109862`.
|
||||
Archived-source Contracts DLL SHA-256:
|
||||
`ebaaa43ffc485288054eb864a59ec59264d8d9c4ea6871319fd7995192370751`.
|
||||
|
||||
That earlier run consumed source only. Actual stable-package proof is recorded
|
||||
above. Consumer-master solution build/review/landing and issue handling are owned
|
||||
by the coordinator; no issue comment/close was performed here.
|
||||
No issue comment/close, package publication, or HG user-checkout modification has
|
||||
been performed. Test results will be added after actual execution.
|
||||
|
||||
@@ -112,7 +112,7 @@ new file mode 100644
|
||||
+ await using var server = await Server.StartAsync(tls: true);
|
||||
+ using var adapter = HistorianGatewayClientAdapter.Create(server.Options(), NullLoggerFactory.Instance);
|
||||
+
|
||||
+ var error = await Should.ThrowAsync<HistorianGatewayException>(
|
||||
+ var error = await Should.ThrowAsync<HistorianGatewayUnavailableException>(
|
||||
+ () => adapter.TagExistsAsync("T", Ct).WaitAsync(TimeSpan.FromSeconds(15), Ct));
|
||||
+ output.WriteLine($"TLS rejection: {error}");
|
||||
+ ContainsTlsAuthenticationFailure(error).ShouldBeTrue("the failure must be TLS authentication, not an arbitrary connection failure");
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate the future patch in archives, using published 1.0.0 or exact HG source project references."""
|
||||
import argparse, datetime, hashlib, io, json, os, shutil, subprocess, tarfile, urllib.request
|
||||
import xml.etree.ElementTree as ET
|
||||
from pathlib import Path
|
||||
|
||||
def verify_published_packages(root, consumer, cache, project):
|
||||
relative = Path('src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.csproj')
|
||||
assert (consumer/relative).read_bytes() == (root/relative).read_bytes(), 'Unexpected source-project override'
|
||||
assets = json.loads((consumer/project.parent/'obj/project.assets.json').read_text())
|
||||
assert all(Path(p).resolve() == cache.resolve() for p in assets['packageFolders'])
|
||||
proof = {'no_source_project_reference_override': True, 'packages': {}}
|
||||
for name in ['Client', 'Contracts']:
|
||||
ident = 'ZB.MOM.WW.HistorianGateway.' + name
|
||||
library = assets['libraries'][ident + '/1.0.0']
|
||||
assert library['type'] == 'package'
|
||||
package = cache/ident.lower()/'1.0.0'
|
||||
provenance = json.loads((package/'.nupkg.metadata').read_text())
|
||||
assert provenance['source'].startswith('https://gitea.dohertylan.com/api/packages/dohertj2/nuget')
|
||||
dll = package/'lib/net10.0'/(ident + '.dll')
|
||||
copied = consumer/project.parent/'bin/Release/net10.0'/(ident + '.dll')
|
||||
digest = hashlib.sha256(dll.read_bytes()).hexdigest()
|
||||
assert digest == hashlib.sha256(copied.read_bytes()).hexdigest()
|
||||
nuspec = ET.parse(package/(ident.lower() + '.nuspec'))
|
||||
assert nuspec.findtext('.//{*}version') == '1.0.0'
|
||||
repository = nuspec.find('.//{*}repository')
|
||||
proof['packages'][ident] = {'version': '1.0.0', 'asset_type': 'package',
|
||||
'source': provenance['source'], 'dll_sha256': digest,
|
||||
'nupkg_sha256': hashlib.sha256((package/(ident.lower() + '.1.0.0.nupkg')).read_bytes()).hexdigest(),
|
||||
'repository': repository.attrib if repository is not None else None,
|
||||
'test_bin_dll_matches_package': True}
|
||||
return proof
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--consumer-root', type=Path, required=True)
|
||||
parser.add_argument('--hg-root', type=Path, required=True)
|
||||
parser.add_argument('--hg-commit', default='e4321915ebc5e0704a68ecad21b85c1cc1c80d6b')
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
a = parser.parse_args(); root = a.consumer_root.resolve(); out = a.output.resolve()
|
||||
if out.is_relative_to(root) or out.is_relative_to(a.hg_root.resolve()):
|
||||
raise ValueError('Use an output directory outside both checkouts so archived HG does not inherit consumer central-package settings.')
|
||||
out.mkdir(parents=True, exist_ok=False)
|
||||
patch = Path(__file__).with_name('consumer-1.0.0.patch').resolve()
|
||||
project = Path('tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Tests.csproj')
|
||||
sha = subprocess.check_output(['git','-C',str(root),'rev-parse','HEAD'],text=True).strip()
|
||||
hg_sha = subprocess.check_output(['git','-C',str(a.hg_root),'rev-parse',a.hg_commit],text=True).strip()
|
||||
def archive(repo, rev, target):
|
||||
target.mkdir()
|
||||
data = subprocess.check_output(['git','-C',str(repo),'archive',rev])
|
||||
with tarfile.open(fileobj=io.BytesIO(data)) as tar: tar.extractall(target, filter='data')
|
||||
|
||||
versions = {}
|
||||
for name in ['client','contracts']:
|
||||
url = 'https://gitea.dohertylan.com/api/packages/dohertj2/nuget/package/zb.mom.ww.historiangateway.' + name + '/index.json'
|
||||
versions[name] = json.load(urllib.request.urlopen(url,timeout=20))['versions']
|
||||
published = all('1.0.0' in v for v in versions.values())
|
||||
metadata = {'utc':datetime.datetime.now(datetime.timezone.utc).isoformat(),'consumer_commit':sha,'hg_snapshot':hg_sha,
|
||||
'mode':'published-1.0.0' if published else 'unreleased-source-project-reference',
|
||||
'feed_versions':versions,'patch_sha256':hashlib.sha256(patch.read_bytes()).hexdigest(),
|
||||
'published_package_verification':published,'normal_package_cache_modified':False}
|
||||
(out/'metadata.json').write_text(json.dumps(metadata,indent=2))
|
||||
consumer = out/'consumer'; archive(root,sha,consumer)
|
||||
subprocess.run(['git','init','-q',str(consumer)],check=True)
|
||||
check = subprocess.run(['git','-C',str(consumer),'apply','--check',str(patch)],capture_output=True,text=True)
|
||||
if check.returncode == 0:
|
||||
subprocess.run(['git','-C',str(consumer),'apply',str(patch)],check=True)
|
||||
metadata['consumer_patch_state'] = 'applied-to-archive'
|
||||
else:
|
||||
reverse = subprocess.run(['git','-C',str(consumer),'apply','--reverse','--check',str(patch)],capture_output=True,text=True)
|
||||
if reverse.returncode:
|
||||
raise RuntimeError('Consumer neither accepts the migration patch nor contains it completely: ' + check.stderr)
|
||||
metadata['consumer_patch_state'] = 'already-present-in-consumer'
|
||||
|
||||
if not published:
|
||||
hg = out/'historiangw-source'; archive(a.hg_root,hg_sha,hg)
|
||||
adapter = consumer/'src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.csproj'
|
||||
tree = ET.parse(adapter)
|
||||
removed = 0
|
||||
for group in tree.getroot().findall('ItemGroup'):
|
||||
for item in list(group):
|
||||
if item.tag=='PackageReference' and item.get('Include') in ['ZB.MOM.WW.HistorianGateway.Client','ZB.MOM.WW.HistorianGateway.Contracts']:
|
||||
group.remove(item);removed += 1
|
||||
assert removed==2
|
||||
group = ET.SubElement(tree.getroot(),'ItemGroup')
|
||||
for relative in ['clients/dotnet/ZB.MOM.WW.HistorianGateway.Client/ZB.MOM.WW.HistorianGateway.Client.csproj',
|
||||
'src/ZB.MOM.WW.HistorianGateway.Contracts/ZB.MOM.WW.HistorianGateway.Contracts.csproj']:
|
||||
ET.SubElement(group,'ProjectReference',Include=str(hg/relative))
|
||||
tree.write(adapter,encoding='unicode')
|
||||
metadata['temporary_override']='Only archived Gateway csproj: two package references replaced by exact archived HG project references; no package packed or published.'
|
||||
# Copy cached dependencies independently, preferably APFS copy-on-write, into the isolated package root.
|
||||
cache = out/'packages'; cache.mkdir()
|
||||
assets = json.loads((root/project.parent/'obj/project.assets.json').read_text())
|
||||
normal = Path(next(iter(assets['packageFolders'])))
|
||||
for library in assets['libraries'].values():
|
||||
if library.get('type')!='package':continue
|
||||
relative = library['path']; source=normal/relative; target=cache/relative
|
||||
target.parent.mkdir(parents=True,exist_ok=True)
|
||||
if target.exists():continue
|
||||
r=subprocess.run(['cp','-cR',str(source),str(target)],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)
|
||||
if r.returncode: shutil.copytree(source,target)
|
||||
config = ET.parse(root/'NuGet.config')
|
||||
for source in config.getroot().find('packageSources'):
|
||||
if source.get('key')=='local-mxgw':
|
||||
local = root/'nuget-packages'
|
||||
if not local.exists():local=out/'empty-local';local.mkdir()
|
||||
source.set('value',str(local))
|
||||
config.write(out/'NuGet.config',encoding='unicode')
|
||||
env=dict(os.environ,NUGET_PACKAGES=str(cache),NUGET_HTTP_CACHE_PATH=str(out/'http-cache'),DOTNET_CLI_HOME=str(out/'dotnet-home'),
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE='1',DOTNET_GENERATE_ASPNET_CERTIFICATE='false',DOTNET_CLI_TELEMETRY_OPTOUT='1')
|
||||
commands=[]
|
||||
def run(args,name):
|
||||
with (out/name).open('w') as log:r=subprocess.run(args,cwd=consumer,env=env,stdout=log,stderr=subprocess.STDOUT)
|
||||
commands.append({'argv':args,'exit':r.returncode,'log':name})
|
||||
(out/'commands.json').write_text(json.dumps(commands,indent=2));print(name,'exit',r.returncode,flush=True)
|
||||
return r.returncode
|
||||
restore = run(['dotnet','restore',str(project),'--configfile',str(out/'NuGet.config'),'--packages',str(cache)],'restore.log')
|
||||
metadata['restore_exit']=restore
|
||||
if restore:
|
||||
(out/'metadata.json').write_text(json.dumps(metadata,indent=2));raise SystemExit(restore)
|
||||
results=out/'test-results'
|
||||
test = run(['dotnet','test',str(project),'-c','Release','--no-restore','--logger','trx','--results-directory',str(results)],'test.log')
|
||||
guard_env=env.copy();guard_env['MIN_EXECUTED']='1'
|
||||
with (out/'guard.log').open('w') as log:
|
||||
guard=subprocess.run(['bash',str(consumer/'scripts/ci/assert-not-all-skipped.sh'),*[str(p) for p in results.glob('*.trx')]],env=guard_env,stdout=log,stderr=subprocess.STDOUT)
|
||||
metadata.update({'test_exit':test,'guard_exit':guard.returncode})
|
||||
ns={'t':'http://microsoft.com/schemas/VisualStudio/TeamTest/2010'}
|
||||
metadata['results']=[]
|
||||
for trx in results.glob('*.trx'):
|
||||
xml=ET.parse(trx);metadata['results'].append(xml.find('.//t:Counters',ns).attrib)
|
||||
metadata['tls_cases']=[{'name':r.get('testName'),'outcome':r.get('outcome'),'output':'\n'.join(p.text or '' for p in r.findall('.//t:StdOut',ns)),
|
||||
'error':r.findtext('.//t:Message','',ns)} for r in xml.findall('.//t:UnitTestResult',ns) if 'HistorianGatewayTlsPolicyWireTests' in r.get('testName','')]
|
||||
if published:
|
||||
metadata['package_proof'] = verify_published_packages(root, consumer, cache, project)
|
||||
(out/'metadata.json').write_text(json.dumps(metadata,indent=2));print(json.dumps(metadata,indent=2),flush=True)
|
||||
raise SystemExit(test if test else guard.returncode)
|
||||
@@ -92,24 +92,5 @@ sessions/subscriptions/items returned to zero after every cycle. Warm samples
|
||||
showed 146–148 total FDs; the final managed heap was 4,737,536 bytes and RSS was
|
||||
181,018,624 bytes. The deliberate manager before/after control passed and
|
||||
`--full --duration 90` exited 2 before creating artifacts. This is diagnostic
|
||||
coverage only; the two-hour gate was pending at that point. The completed full
|
||||
run is recorded below. Receipts are under `evidence/2026-11-10-diagnostic/`.
|
||||
|
||||
|
||||
The coordinator-owned full run completed on 2026-11-10 with **exit 0 and
|
||||
7,200.984 seconds of actual client observation**: 5,420 cycles; 10,840 Shared
|
||||
rounds, 10,840 driver rounds plus 10,840 live reinitializations, 10,840 browser
|
||||
sessions, and **43,360 verified manager disposals**. All samples report zero weak
|
||||
product-object survivors and zero open PKI descriptors; each cycle returned server
|
||||
public session/subscription/item counts to zero. Final retained managed memory was
|
||||
3,988,520 bytes and RSS 86,102,016 bytes, with 148 global FDs. Own certificate hashes
|
||||
were unchanged. The manager before/after positive control passed. Selected counter
|
||||
histories, loaded SDK hashes, artifact manifest and verification hashes are in
|
||||
`evidence/2026-11-10-full/`; private PKI and credentials are excluded.
|
||||
|
||||
This is a **completed two-hour client lifecycle gate**, not a performance-budget
|
||||
or complete G4 pass. Its source is `c25561c6`, exact SDK 2.0.1, framework-dependent
|
||||
Linux ARM64 on runtime 10.0.3 with the pinned image ID recorded in the receipt.
|
||||
The later HG 1.0 consumer mapping is independently tested and does not retroactively
|
||||
change these immutable artifact/source records. The failed canonical server RSS
|
||||
workload remains separate in #799.
|
||||
coverage only; the two-hour gate remains pending until a coordinator-owned full
|
||||
run completes. Receipts are under `evidence/2026-11-10-diagnostic/`.
|
||||
|
||||
-2142
File diff suppressed because it is too large
Load Diff
@@ -1,543 +0,0 @@
|
||||
{"cycle":0,"elapsedSeconds":0,"utc":"2026-11-10T17:44:45.1152841Z","WorkingSet64":50864128,"PrivateMemorySize64":87015424,"managedBytes":243368,"allocatedBytes":307672,"gc":[2,2,2],"fdCount":66,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":0,"sharedPasses":0,"driverPasses":0,"browserPasses":0}
|
||||
{"cycle":10,"elapsedSeconds":13.7695273,"utc":"2026-11-10T17:44:58.8996774Z","WorkingSet64":169111552,"PrivateMemorySize64":210857984,"managedBytes":4700728,"allocatedBytes":53463728,"gc":[5,4,4],"fdCount":146,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":80,"sharedPasses":20,"driverPasses":20,"browserPasses":20}
|
||||
{"cycle":20,"elapsedSeconds":26.9702703,"utc":"2026-11-10T17:45:12.0945318Z","WorkingSet64":180752384,"PrivateMemorySize64":220975104,"managedBytes":4635880,"allocatedBytes":100195000,"gc":[8,6,6],"fdCount":146,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":160,"sharedPasses":40,"driverPasses":40,"browserPasses":40}
|
||||
{"cycle":30,"elapsedSeconds":40.1833927,"utc":"2026-11-10T17:45:25.3056621Z","WorkingSet64":181284864,"PrivateMemorySize64":221257728,"managedBytes":4635304,"allocatedBytes":146914520,"gc":[11,8,8],"fdCount":146,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":240,"sharedPasses":60,"driverPasses":60,"browserPasses":60}
|
||||
{"cycle":40,"elapsedSeconds":53.432775,"utc":"2026-11-10T17:45:38.5592881Z","WorkingSet64":182726656,"PrivateMemorySize64":223703040,"managedBytes":4651128,"allocatedBytes":193645336,"gc":[14,10,10],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":320,"sharedPasses":80,"driverPasses":80,"browserPasses":80}
|
||||
{"cycle":50,"elapsedSeconds":66.6594264,"utc":"2026-11-10T17:45:51.7879085Z","WorkingSet64":184299520,"PrivateMemorySize64":223821824,"managedBytes":4512664,"allocatedBytes":240338112,"gc":[17,12,12],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":400,"sharedPasses":100,"driverPasses":100,"browserPasses":100}
|
||||
{"cycle":60,"elapsedSeconds":79.9231462,"utc":"2026-11-10T17:46:05.0408096Z","WorkingSet64":181075968,"PrivateMemorySize64":223862784,"managedBytes":4512712,"allocatedBytes":287040456,"gc":[20,14,14],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":480,"sharedPasses":120,"driverPasses":120,"browserPasses":120}
|
||||
{"cycle":70,"elapsedSeconds":93.1568589,"utc":"2026-11-10T17:46:18.2833867Z","WorkingSet64":181616640,"PrivateMemorySize64":225923072,"managedBytes":4513064,"allocatedBytes":333750808,"gc":[23,16,16],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":560,"sharedPasses":140,"driverPasses":140,"browserPasses":140}
|
||||
{"cycle":80,"elapsedSeconds":106.4112548,"utc":"2026-11-10T17:46:31.5394096Z","WorkingSet64":182919168,"PrivateMemorySize64":226041856,"managedBytes":4513088,"allocatedBytes":380449960,"gc":[26,18,18],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":640,"sharedPasses":160,"driverPasses":160,"browserPasses":160}
|
||||
{"cycle":90,"elapsedSeconds":119.5485812,"utc":"2026-11-10T17:46:44.6748037Z","WorkingSet64":182964224,"PrivateMemorySize64":226074624,"managedBytes":4514752,"allocatedBytes":427140400,"gc":[29,20,20],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":720,"sharedPasses":180,"driverPasses":180,"browserPasses":180}
|
||||
{"cycle":100,"elapsedSeconds":132.7817233,"utc":"2026-11-10T17:46:57.905311Z","WorkingSet64":141791232,"PrivateMemorySize64":226054144,"managedBytes":4513568,"allocatedBytes":473846752,"gc":[32,22,22],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":800,"sharedPasses":200,"driverPasses":200,"browserPasses":200}
|
||||
{"cycle":110,"elapsedSeconds":146.0640883,"utc":"2026-11-10T17:47:11.1836839Z","WorkingSet64":141873152,"PrivateMemorySize64":226054144,"managedBytes":4512456,"allocatedBytes":520551464,"gc":[35,24,24],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":880,"sharedPasses":220,"driverPasses":220,"browserPasses":220}
|
||||
{"cycle":120,"elapsedSeconds":159.240507,"utc":"2026-11-10T17:47:24.357642Z","WorkingSet64":142090240,"PrivateMemorySize64":226074624,"managedBytes":4578864,"allocatedBytes":567333592,"gc":[38,26,26],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":960,"sharedPasses":240,"driverPasses":240,"browserPasses":240}
|
||||
{"cycle":130,"elapsedSeconds":172.3592901,"utc":"2026-11-10T17:47:37.4808822Z","WorkingSet64":140406784,"PrivateMemorySize64":226164736,"managedBytes":4627496,"allocatedBytes":614112792,"gc":[41,28,28],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1040,"sharedPasses":260,"driverPasses":260,"browserPasses":260}
|
||||
{"cycle":140,"elapsedSeconds":185.6255455,"utc":"2026-11-10T17:47:50.7528131Z","WorkingSet64":140435456,"PrivateMemorySize64":226197504,"managedBytes":4635744,"allocatedBytes":660820104,"gc":[44,30,30],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1120,"sharedPasses":280,"driverPasses":280,"browserPasses":280}
|
||||
{"cycle":150,"elapsedSeconds":198.8420396,"utc":"2026-11-10T17:48:03.9622808Z","WorkingSet64":140603392,"PrivateMemorySize64":226217984,"managedBytes":4526896,"allocatedBytes":707533128,"gc":[47,32,32],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1200,"sharedPasses":300,"driverPasses":300,"browserPasses":300}
|
||||
{"cycle":160,"elapsedSeconds":212.0768585,"utc":"2026-11-10T17:48:17.2025904Z","WorkingSet64":135364608,"PrivateMemorySize64":226217984,"managedBytes":4525584,"allocatedBytes":754256240,"gc":[50,34,34],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1280,"sharedPasses":320,"driverPasses":320,"browserPasses":320}
|
||||
{"cycle":170,"elapsedSeconds":225.286241,"utc":"2026-11-10T17:48:30.4084106Z","WorkingSet64":136687616,"PrivateMemorySize64":226197504,"managedBytes":4626624,"allocatedBytes":801068648,"gc":[53,36,36],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1360,"sharedPasses":340,"driverPasses":340,"browserPasses":340}
|
||||
{"cycle":180,"elapsedSeconds":238.5631894,"utc":"2026-11-10T17:48:43.68748Z","WorkingSet64":136933376,"PrivateMemorySize64":226217984,"managedBytes":4509904,"allocatedBytes":847775352,"gc":[56,38,38],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1440,"sharedPasses":360,"driverPasses":360,"browserPasses":360}
|
||||
{"cycle":190,"elapsedSeconds":252.0181175,"utc":"2026-11-10T17:48:57.1406338Z","WorkingSet64":136933376,"PrivateMemorySize64":226197504,"managedBytes":4560984,"allocatedBytes":894536040,"gc":[59,40,40],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1520,"sharedPasses":380,"driverPasses":380,"browserPasses":380}
|
||||
{"cycle":200,"elapsedSeconds":265.2363293,"utc":"2026-11-10T17:49:10.3618643Z","WorkingSet64":136785920,"PrivateMemorySize64":226177024,"managedBytes":4513696,"allocatedBytes":941251664,"gc":[62,42,42],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1600,"sharedPasses":400,"driverPasses":400,"browserPasses":400}
|
||||
{"cycle":210,"elapsedSeconds":278.4993127,"utc":"2026-11-10T17:49:23.6257057Z","WorkingSet64":136945664,"PrivateMemorySize64":226254848,"managedBytes":4513856,"allocatedBytes":987976336,"gc":[65,44,44],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1680,"sharedPasses":420,"driverPasses":420,"browserPasses":420}
|
||||
{"cycle":220,"elapsedSeconds":291.8139272,"utc":"2026-11-10T17:49:36.945777Z","WorkingSet64":136957952,"PrivateMemorySize64":226254848,"managedBytes":4513000,"allocatedBytes":1034681632,"gc":[68,46,46],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1760,"sharedPasses":440,"driverPasses":440,"browserPasses":440}
|
||||
{"cycle":230,"elapsedSeconds":305.2256216,"utc":"2026-11-10T17:49:50.3539024Z","WorkingSet64":139825152,"PrivateMemorySize64":227258368,"managedBytes":4513704,"allocatedBytes":1082343824,"gc":[71,48,48],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1840,"sharedPasses":460,"driverPasses":460,"browserPasses":460}
|
||||
{"cycle":240,"elapsedSeconds":318.7210006,"utc":"2026-11-10T17:50:03.8442729Z","WorkingSet64":140492800,"PrivateMemorySize64":227385344,"managedBytes":4513552,"allocatedBytes":1129039640,"gc":[74,50,50],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":1920,"sharedPasses":480,"driverPasses":480,"browserPasses":480}
|
||||
{"cycle":250,"elapsedSeconds":332.1604191,"utc":"2026-11-10T17:50:17.2844081Z","WorkingSet64":140492800,"PrivateMemorySize64":227385344,"managedBytes":4515080,"allocatedBytes":1175757536,"gc":[77,52,52],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2000,"sharedPasses":500,"driverPasses":500,"browserPasses":500}
|
||||
{"cycle":260,"elapsedSeconds":345.4675957,"utc":"2026-11-10T17:50:30.5895307Z","WorkingSet64":139522048,"PrivateMemorySize64":227418112,"managedBytes":4514784,"allocatedBytes":1222459552,"gc":[80,54,54],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2080,"sharedPasses":520,"driverPasses":520,"browserPasses":520}
|
||||
{"cycle":270,"elapsedSeconds":358.769662,"utc":"2026-11-10T17:50:43.8952358Z","WorkingSet64":139931648,"PrivateMemorySize64":227463168,"managedBytes":4651760,"allocatedBytes":1269298688,"gc":[83,56,56],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2160,"sharedPasses":540,"driverPasses":540,"browserPasses":540}
|
||||
{"cycle":280,"elapsedSeconds":372.1252106,"utc":"2026-11-10T17:50:57.2428981Z","WorkingSet64":140324864,"PrivateMemorySize64":235986944,"managedBytes":4570704,"allocatedBytes":1315990496,"gc":[86,58,58],"fdCount":150,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2240,"sharedPasses":560,"driverPasses":560,"browserPasses":560}
|
||||
{"cycle":290,"elapsedSeconds":385.4714765,"utc":"2026-11-10T17:51:10.5985393Z","WorkingSet64":140390400,"PrivateMemorySize64":236068864,"managedBytes":4634576,"allocatedBytes":1362782352,"gc":[89,60,60],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2320,"sharedPasses":580,"driverPasses":580,"browserPasses":580}
|
||||
{"cycle":300,"elapsedSeconds":398.7827818,"utc":"2026-11-10T17:51:23.9097834Z","WorkingSet64":139005952,"PrivateMemorySize64":236068864,"managedBytes":4652400,"allocatedBytes":1409489328,"gc":[92,62,62],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2400,"sharedPasses":600,"driverPasses":600,"browserPasses":600}
|
||||
{"cycle":310,"elapsedSeconds":412.2199569,"utc":"2026-11-10T17:51:37.3401855Z","WorkingSet64":143712256,"PrivateMemorySize64":237314048,"managedBytes":4527064,"allocatedBytes":1456208880,"gc":[95,64,64],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2480,"sharedPasses":620,"driverPasses":620,"browserPasses":620}
|
||||
{"cycle":320,"elapsedSeconds":425.5244319,"utc":"2026-11-10T17:51:50.6490664Z","WorkingSet64":144027648,"PrivateMemorySize64":237314048,"managedBytes":4569400,"allocatedBytes":1502963424,"gc":[98,66,66],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2560,"sharedPasses":640,"driverPasses":640,"browserPasses":640}
|
||||
{"cycle":330,"elapsedSeconds":438.932473,"utc":"2026-11-10T17:52:04.0498994Z","WorkingSet64":141996032,"PrivateMemorySize64":237293568,"managedBytes":4562136,"allocatedBytes":1549665464,"gc":[101,68,68],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2640,"sharedPasses":660,"driverPasses":660,"browserPasses":660}
|
||||
{"cycle":340,"elapsedSeconds":452.164949,"utc":"2026-11-10T17:52:17.2886751Z","WorkingSet64":141996032,"PrivateMemorySize64":237273088,"managedBytes":4512880,"allocatedBytes":1596374080,"gc":[104,70,70],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2720,"sharedPasses":680,"driverPasses":680,"browserPasses":680}
|
||||
{"cycle":350,"elapsedSeconds":465.404458,"utc":"2026-11-10T17:52:30.528482Z","WorkingSet64":141996032,"PrivateMemorySize64":237293568,"managedBytes":4588024,"allocatedBytes":1643160240,"gc":[107,72,72],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2800,"sharedPasses":700,"driverPasses":700,"browserPasses":700}
|
||||
{"cycle":360,"elapsedSeconds":478.6179186,"utc":"2026-11-10T17:52:43.7430573Z","WorkingSet64":142000128,"PrivateMemorySize64":237277184,"managedBytes":4513000,"allocatedBytes":1689870792,"gc":[110,74,74],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2880,"sharedPasses":720,"driverPasses":720,"browserPasses":720}
|
||||
{"cycle":370,"elapsedSeconds":491.876047,"utc":"2026-11-10T17:52:57.0080243Z","WorkingSet64":139350016,"PrivateMemorySize64":237277184,"managedBytes":4513576,"allocatedBytes":1736584040,"gc":[113,76,76],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":2960,"sharedPasses":740,"driverPasses":740,"browserPasses":740}
|
||||
{"cycle":380,"elapsedSeconds":505.1403319,"utc":"2026-11-10T17:53:10.259606Z","WorkingSet64":139354112,"PrivateMemorySize64":237297664,"managedBytes":4544344,"allocatedBytes":1783307464,"gc":[116,78,78],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3040,"sharedPasses":760,"driverPasses":760,"browserPasses":760}
|
||||
{"cycle":390,"elapsedSeconds":518.3707659,"utc":"2026-11-10T17:53:23.4942486Z","WorkingSet64":135155712,"PrivateMemorySize64":233123840,"managedBytes":4536360,"allocatedBytes":1830117816,"gc":[119,80,80],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3120,"sharedPasses":780,"driverPasses":780,"browserPasses":780}
|
||||
{"cycle":400,"elapsedSeconds":531.586656,"utc":"2026-11-10T17:53:36.7128434Z","WorkingSet64":134750208,"PrivateMemorySize64":237146112,"managedBytes":4561408,"allocatedBytes":1876833480,"gc":[122,82,82],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3200,"sharedPasses":800,"driverPasses":800,"browserPasses":800}
|
||||
{"cycle":410,"elapsedSeconds":544.8171966,"utc":"2026-11-10T17:53:49.9469169Z","WorkingSet64":134901760,"PrivateMemorySize64":237297664,"managedBytes":4502384,"allocatedBytes":1923530968,"gc":[125,84,84],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3280,"sharedPasses":820,"driverPasses":820,"browserPasses":820}
|
||||
{"cycle":420,"elapsedSeconds":558.0481703,"utc":"2026-11-10T17:54:03.1707399Z","WorkingSet64":134901760,"PrivateMemorySize64":237297664,"managedBytes":4547616,"allocatedBytes":1970293824,"gc":[128,86,86],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3360,"sharedPasses":840,"driverPasses":840,"browserPasses":840}
|
||||
{"cycle":430,"elapsedSeconds":571.2732878,"utc":"2026-11-10T17:54:16.3976731Z","WorkingSet64":134008832,"PrivateMemorySize64":237309952,"managedBytes":4561616,"allocatedBytes":2017029208,"gc":[131,88,88],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3440,"sharedPasses":860,"driverPasses":860,"browserPasses":860}
|
||||
{"cycle":440,"elapsedSeconds":584.4426453,"utc":"2026-11-10T17:54:29.563521Z","WorkingSet64":134336512,"PrivateMemorySize64":237289472,"managedBytes":4512936,"allocatedBytes":2063758408,"gc":[134,90,90],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3520,"sharedPasses":880,"driverPasses":880,"browserPasses":880}
|
||||
{"cycle":450,"elapsedSeconds":597.6619216,"utc":"2026-11-10T17:54:42.786555Z","WorkingSet64":134467584,"PrivateMemorySize64":237330432,"managedBytes":4637512,"allocatedBytes":2110581488,"gc":[137,92,92],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3600,"sharedPasses":900,"driverPasses":900,"browserPasses":900}
|
||||
{"cycle":460,"elapsedSeconds":610.9003191,"utc":"2026-11-10T17:54:56.0332862Z","WorkingSet64":138235904,"PrivateMemorySize64":237772800,"managedBytes":4635240,"allocatedBytes":2158245944,"gc":[140,94,94],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3680,"sharedPasses":920,"driverPasses":920,"browserPasses":920}
|
||||
{"cycle":470,"elapsedSeconds":624.0978198,"utc":"2026-11-10T17:55:09.2278067Z","WorkingSet64":137936896,"PrivateMemorySize64":237772800,"managedBytes":4652232,"allocatedBytes":2204953080,"gc":[143,96,96],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3760,"sharedPasses":940,"driverPasses":940,"browserPasses":940}
|
||||
{"cycle":480,"elapsedSeconds":637.3568307,"utc":"2026-11-10T17:55:22.4794072Z","WorkingSet64":137936896,"PrivateMemorySize64":237752320,"managedBytes":4644040,"allocatedBytes":2251661136,"gc":[146,98,98],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3840,"sharedPasses":960,"driverPasses":960,"browserPasses":960}
|
||||
{"cycle":490,"elapsedSeconds":650.5736842,"utc":"2026-11-10T17:55:35.6980521Z","WorkingSet64":137936896,"PrivateMemorySize64":237731840,"managedBytes":4579352,"allocatedBytes":2298383520,"gc":[149,100,100],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":3920,"sharedPasses":980,"driverPasses":980,"browserPasses":980}
|
||||
{"cycle":500,"elapsedSeconds":663.8366705,"utc":"2026-11-10T17:55:48.9564326Z","WorkingSet64":137097216,"PrivateMemorySize64":237731840,"managedBytes":4577824,"allocatedBytes":2345077424,"gc":[152,102,102],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4000,"sharedPasses":1000,"driverPasses":1000,"browserPasses":1000}
|
||||
{"cycle":510,"elapsedSeconds":677.065381,"utc":"2026-11-10T17:56:02.1904476Z","WorkingSet64":137097216,"PrivateMemorySize64":237731840,"managedBytes":4578392,"allocatedBytes":2391771280,"gc":[155,104,104],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4080,"sharedPasses":1020,"driverPasses":1020,"browserPasses":1020}
|
||||
{"cycle":520,"elapsedSeconds":690.3065052,"utc":"2026-11-10T17:56:15.4309025Z","WorkingSet64":137097216,"PrivateMemorySize64":237731840,"managedBytes":4578232,"allocatedBytes":2438474944,"gc":[158,106,106],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4160,"sharedPasses":1040,"driverPasses":1040,"browserPasses":1040}
|
||||
{"cycle":530,"elapsedSeconds":703.4412912,"utc":"2026-11-10T17:56:28.5628852Z","WorkingSet64":137101312,"PrivateMemorySize64":237772800,"managedBytes":4634600,"allocatedBytes":2485236424,"gc":[161,108,108],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4240,"sharedPasses":1060,"driverPasses":1060,"browserPasses":1060}
|
||||
{"cycle":540,"elapsedSeconds":716.6648568,"utc":"2026-11-10T17:56:41.7843237Z","WorkingSet64":132005888,"PrivateMemorySize64":237752320,"managedBytes":4626344,"allocatedBytes":2531930208,"gc":[164,110,110],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4320,"sharedPasses":1080,"driverPasses":1080,"browserPasses":1080}
|
||||
{"cycle":550,"elapsedSeconds":729.8734274,"utc":"2026-11-10T17:56:54.9987459Z","WorkingSet64":132448256,"PrivateMemorySize64":237772800,"managedBytes":4702632,"allocatedBytes":2578769528,"gc":[167,112,112],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4400,"sharedPasses":1100,"driverPasses":1100,"browserPasses":1100}
|
||||
{"cycle":560,"elapsedSeconds":743.4933317,"utc":"2026-11-10T17:57:08.6107867Z","WorkingSet64":132493312,"PrivateMemorySize64":237772800,"managedBytes":4683496,"allocatedBytes":2625488256,"gc":[170,114,114],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4480,"sharedPasses":1120,"driverPasses":1120,"browserPasses":1120}
|
||||
{"cycle":570,"elapsedSeconds":756.652478,"utc":"2026-11-10T17:57:21.7778734Z","WorkingSet64":133828608,"PrivateMemorySize64":237772800,"managedBytes":4652704,"allocatedBytes":2672259440,"gc":[173,116,116],"fdCount":150,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4560,"sharedPasses":1140,"driverPasses":1140,"browserPasses":1140}
|
||||
{"cycle":580,"elapsedSeconds":769.9148879,"utc":"2026-11-10T17:57:35.0416181Z","WorkingSet64":134316032,"PrivateMemorySize64":237740032,"managedBytes":4514344,"allocatedBytes":2718962144,"gc":[176,118,118],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4640,"sharedPasses":1160,"driverPasses":1160,"browserPasses":1160}
|
||||
{"cycle":590,"elapsedSeconds":783.1432993,"utc":"2026-11-10T17:57:48.2637812Z","WorkingSet64":135409664,"PrivateMemorySize64":237780992,"managedBytes":4635536,"allocatedBytes":2765793352,"gc":[179,120,120],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4720,"sharedPasses":1180,"driverPasses":1180,"browserPasses":1180}
|
||||
{"cycle":600,"elapsedSeconds":796.3965915,"utc":"2026-11-10T17:58:01.5236438Z","WorkingSet64":136241152,"PrivateMemorySize64":238190592,"managedBytes":4636328,"allocatedBytes":2812497264,"gc":[182,122,122],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4800,"sharedPasses":1200,"driverPasses":1200,"browserPasses":1200}
|
||||
{"cycle":610,"elapsedSeconds":809.6451522,"utc":"2026-11-10T17:58:14.7728315Z","WorkingSet64":140668928,"PrivateMemorySize64":244002816,"managedBytes":4644960,"allocatedBytes":2859208272,"gc":[185,124,124],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4880,"sharedPasses":1220,"driverPasses":1220,"browserPasses":1220}
|
||||
{"cycle":620,"elapsedSeconds":822.8248692,"utc":"2026-11-10T17:58:27.9516206Z","WorkingSet64":140668928,"PrivateMemorySize64":243982336,"managedBytes":4580712,"allocatedBytes":2905911480,"gc":[188,126,126],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":4960,"sharedPasses":1240,"driverPasses":1240,"browserPasses":1240}
|
||||
{"cycle":630,"elapsedSeconds":836.1274925,"utc":"2026-11-10T17:58:41.2503909Z","WorkingSet64":140668928,"PrivateMemorySize64":244023296,"managedBytes":4767544,"allocatedBytes":2952795848,"gc":[191,128,128],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5040,"sharedPasses":1260,"driverPasses":1260,"browserPasses":1260}
|
||||
{"cycle":640,"elapsedSeconds":849.3561003,"utc":"2026-11-10T17:58:54.485024Z","WorkingSet64":140599296,"PrivateMemorySize64":244023296,"managedBytes":4767584,"allocatedBytes":2999516072,"gc":[194,130,130],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5120,"sharedPasses":1280,"driverPasses":1280,"browserPasses":1280}
|
||||
{"cycle":650,"elapsedSeconds":862.6303684,"utc":"2026-11-10T17:59:07.7554554Z","WorkingSet64":140640256,"PrivateMemorySize64":244002816,"managedBytes":4628280,"allocatedBytes":3046210632,"gc":[197,132,132],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5200,"sharedPasses":1300,"driverPasses":1300,"browserPasses":1300}
|
||||
{"cycle":660,"elapsedSeconds":875.9574451,"utc":"2026-11-10T17:59:21.0839627Z","WorkingSet64":140705792,"PrivateMemorySize64":244002816,"managedBytes":4645496,"allocatedBytes":3092929440,"gc":[200,134,134],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5280,"sharedPasses":1320,"driverPasses":1320,"browserPasses":1320}
|
||||
{"cycle":670,"elapsedSeconds":889.3266363,"utc":"2026-11-10T17:59:34.4479619Z","WorkingSet64":138076160,"PrivateMemorySize64":244002816,"managedBytes":4645128,"allocatedBytes":3139625752,"gc":[203,136,136],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5360,"sharedPasses":1340,"driverPasses":1340,"browserPasses":1340}
|
||||
{"cycle":680,"elapsedSeconds":902.5676055,"utc":"2026-11-10T17:59:47.6941683Z","WorkingSet64":138649600,"PrivateMemorySize64":244002816,"managedBytes":4644224,"allocatedBytes":3187309400,"gc":[206,138,138],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5440,"sharedPasses":1360,"driverPasses":1360,"browserPasses":1360}
|
||||
{"cycle":690,"elapsedSeconds":915.8708291,"utc":"2026-11-10T18:00:00.9905254Z","WorkingSet64":138649600,"PrivateMemorySize64":244002816,"managedBytes":4627224,"allocatedBytes":3234022344,"gc":[209,140,140],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5520,"sharedPasses":1380,"driverPasses":1380,"browserPasses":1380}
|
||||
{"cycle":700,"elapsedSeconds":929.1957975,"utc":"2026-11-10T18:00:14.3130841Z","WorkingSet64":138649600,"PrivateMemorySize64":244002816,"managedBytes":4619800,"allocatedBytes":3280726800,"gc":[212,142,142],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5600,"sharedPasses":1400,"driverPasses":1400,"browserPasses":1400}
|
||||
{"cycle":710,"elapsedSeconds":942.4586542,"utc":"2026-11-10T18:00:27.586475Z","WorkingSet64":135946240,"PrivateMemorySize64":244002816,"managedBytes":4628968,"allocatedBytes":3327444728,"gc":[215,144,144],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5680,"sharedPasses":1420,"driverPasses":1420,"browserPasses":1420}
|
||||
{"cycle":720,"elapsedSeconds":955.7505247,"utc":"2026-11-10T18:00:40.8724218Z","WorkingSet64":135958528,"PrivateMemorySize64":244023296,"managedBytes":4628968,"allocatedBytes":3374155568,"gc":[218,146,146],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5760,"sharedPasses":1440,"driverPasses":1440,"browserPasses":1440}
|
||||
{"cycle":730,"elapsedSeconds":969.0838894,"utc":"2026-11-10T18:00:54.2049363Z","WorkingSet64":136417280,"PrivateMemorySize64":244023296,"managedBytes":4516824,"allocatedBytes":3420859040,"gc":[221,148,148],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5840,"sharedPasses":1460,"driverPasses":1460,"browserPasses":1460}
|
||||
{"cycle":740,"elapsedSeconds":982.3943025,"utc":"2026-11-10T18:01:07.5128133Z","WorkingSet64":134074368,"PrivateMemorySize64":244023296,"managedBytes":4629808,"allocatedBytes":3467677680,"gc":[224,150,150],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":5920,"sharedPasses":1480,"driverPasses":1480,"browserPasses":1480}
|
||||
{"cycle":750,"elapsedSeconds":995.6763152,"utc":"2026-11-10T18:01:20.7968671Z","WorkingSet64":134213632,"PrivateMemorySize64":244158464,"managedBytes":4707312,"allocatedBytes":3514541584,"gc":[227,152,152],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6000,"sharedPasses":1500,"driverPasses":1500,"browserPasses":1500}
|
||||
{"cycle":760,"elapsedSeconds":1008.9962837,"utc":"2026-11-10T18:01:34.1196181Z","WorkingSet64":134389760,"PrivateMemorySize64":244310016,"managedBytes":4611496,"allocatedBytes":3561239752,"gc":[230,154,154],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6080,"sharedPasses":1520,"driverPasses":1520,"browserPasses":1520}
|
||||
{"cycle":770,"elapsedSeconds":1022.3235328,"utc":"2026-11-10T18:01:47.4463324Z","WorkingSet64":133943296,"PrivateMemorySize64":244477952,"managedBytes":4525248,"allocatedBytes":3607968032,"gc":[233,156,156],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6160,"sharedPasses":1540,"driverPasses":1540,"browserPasses":1540}
|
||||
{"cycle":780,"elapsedSeconds":1035.6194261,"utc":"2026-11-10T18:02:00.7433573Z","WorkingSet64":134066176,"PrivateMemorySize64":244477952,"managedBytes":4525144,"allocatedBytes":3654681832,"gc":[236,158,158],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6240,"sharedPasses":1560,"driverPasses":1560,"browserPasses":1560}
|
||||
{"cycle":790,"elapsedSeconds":1048.9445312,"utc":"2026-11-10T18:02:14.0619801Z","WorkingSet64":134283264,"PrivateMemorySize64":244641792,"managedBytes":4525200,"allocatedBytes":3701398480,"gc":[239,160,160],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6320,"sharedPasses":1580,"driverPasses":1580,"browserPasses":1580}
|
||||
{"cycle":800,"elapsedSeconds":1062.5263877,"utc":"2026-11-10T18:02:27.6482991Z","WorkingSet64":135147520,"PrivateMemorySize64":244621312,"managedBytes":4652720,"allocatedBytes":3748232504,"gc":[242,162,162],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6400,"sharedPasses":1600,"driverPasses":1600,"browserPasses":1600}
|
||||
{"cycle":810,"elapsedSeconds":1075.9020195,"utc":"2026-11-10T18:02:41.0260759Z","WorkingSet64":134098944,"PrivateMemorySize64":244645888,"managedBytes":4644840,"allocatedBytes":3794926744,"gc":[245,164,164],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6480,"sharedPasses":1620,"driverPasses":1620,"browserPasses":1620}
|
||||
{"cycle":820,"elapsedSeconds":1089.2480793,"utc":"2026-11-10T18:02:54.3736896Z","WorkingSet64":134152192,"PrivateMemorySize64":244645888,"managedBytes":4626696,"allocatedBytes":3841641744,"gc":[248,166,166],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6560,"sharedPasses":1640,"driverPasses":1640,"browserPasses":1640}
|
||||
{"cycle":830,"elapsedSeconds":1102.5923236,"utc":"2026-11-10T18:03:07.7177768Z","WorkingSet64":134152192,"PrivateMemorySize64":244645888,"managedBytes":4627632,"allocatedBytes":3888364424,"gc":[251,168,168],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6640,"sharedPasses":1660,"driverPasses":1660,"browserPasses":1660}
|
||||
{"cycle":840,"elapsedSeconds":1115.893989,"utc":"2026-11-10T18:03:21.0117452Z","WorkingSet64":133316608,"PrivateMemorySize64":244690944,"managedBytes":4687752,"allocatedBytes":3935138320,"gc":[254,170,170],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6720,"sharedPasses":1680,"driverPasses":1680,"browserPasses":1680}
|
||||
{"cycle":850,"elapsedSeconds":1129.1850949,"utc":"2026-11-10T18:03:34.3027344Z","WorkingSet64":133316608,"PrivateMemorySize64":244649984,"managedBytes":4514696,"allocatedBytes":3981852688,"gc":[257,172,172],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6800,"sharedPasses":1700,"driverPasses":1700,"browserPasses":1700}
|
||||
{"cycle":860,"elapsedSeconds":1143.2609207,"utc":"2026-11-10T18:03:48.3843547Z","WorkingSet64":133566464,"PrivateMemorySize64":244674560,"managedBytes":4512416,"allocatedBytes":4028560504,"gc":[260,174,174],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6880,"sharedPasses":1720,"driverPasses":1720,"browserPasses":1720}
|
||||
{"cycle":870,"elapsedSeconds":1156.5442235,"utc":"2026-11-10T18:04:01.6618093Z","WorkingSet64":133566464,"PrivateMemorySize64":244715520,"managedBytes":4701456,"allocatedBytes":4075436064,"gc":[263,176,176],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":6960,"sharedPasses":1740,"driverPasses":1740,"browserPasses":1740}
|
||||
{"cycle":880,"elapsedSeconds":1169.8395465,"utc":"2026-11-10T18:04:14.9592413Z","WorkingSet64":133902336,"PrivateMemorySize64":244695040,"managedBytes":4644888,"allocatedBytes":4122145768,"gc":[266,178,178],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7040,"sharedPasses":1760,"driverPasses":1760,"browserPasses":1760}
|
||||
{"cycle":890,"elapsedSeconds":1183.0837681,"utc":"2026-11-10T18:04:28.2057113Z","WorkingSet64":134070272,"PrivateMemorySize64":244695040,"managedBytes":4584936,"allocatedBytes":4168868520,"gc":[269,180,180],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7120,"sharedPasses":1780,"driverPasses":1780,"browserPasses":1780}
|
||||
{"cycle":900,"elapsedSeconds":1196.4124674,"utc":"2026-11-10T18:04:41.5380118Z","WorkingSet64":134070272,"PrivateMemorySize64":244695040,"managedBytes":4644976,"allocatedBytes":4215662424,"gc":[272,182,182],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7200,"sharedPasses":1800,"driverPasses":1800,"browserPasses":1800}
|
||||
{"cycle":910,"elapsedSeconds":1210.8633534,"utc":"2026-11-10T18:04:55.9862313Z","WorkingSet64":140054528,"PrivateMemorySize64":246149120,"managedBytes":4643720,"allocatedBytes":4263326776,"gc":[275,184,184],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7280,"sharedPasses":1820,"driverPasses":1820,"browserPasses":1820}
|
||||
{"cycle":920,"elapsedSeconds":1224.1300185,"utc":"2026-11-10T18:05:09.2476755Z","WorkingSet64":140230656,"PrivateMemorySize64":246317056,"managedBytes":4652544,"allocatedBytes":4310033600,"gc":[278,186,186],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7360,"sharedPasses":1840,"driverPasses":1840,"browserPasses":1840}
|
||||
{"cycle":930,"elapsedSeconds":1237.4599224,"utc":"2026-11-10T18:05:22.5775977Z","WorkingSet64":140271616,"PrivateMemorySize64":246317056,"managedBytes":4576384,"allocatedBytes":4356724040,"gc":[281,188,188],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7440,"sharedPasses":1860,"driverPasses":1860,"browserPasses":1860}
|
||||
{"cycle":940,"elapsedSeconds":1250.6471697,"utc":"2026-11-10T18:05:35.7646176Z","WorkingSet64":139784192,"PrivateMemorySize64":246317056,"managedBytes":4644992,"allocatedBytes":4403505944,"gc":[284,190,190],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7520,"sharedPasses":1880,"driverPasses":1880,"browserPasses":1880}
|
||||
{"cycle":950,"elapsedSeconds":1263.968135,"utc":"2026-11-10T18:05:49.0858797Z","WorkingSet64":139841536,"PrivateMemorySize64":246317056,"managedBytes":4637856,"allocatedBytes":4450208048,"gc":[287,192,192],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7600,"sharedPasses":1900,"driverPasses":1900,"browserPasses":1900}
|
||||
{"cycle":960,"elapsedSeconds":1278.7734837,"utc":"2026-11-10T18:06:03.8909298Z","WorkingSet64":140120064,"PrivateMemorySize64":246337536,"managedBytes":4645120,"allocatedBytes":4496918472,"gc":[290,194,194],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7680,"sharedPasses":1920,"driverPasses":1920,"browserPasses":1920}
|
||||
{"cycle":970,"elapsedSeconds":1291.9503059,"utc":"2026-11-10T18:06:17.07437Z","WorkingSet64":139649024,"PrivateMemorySize64":246317056,"managedBytes":4644960,"allocatedBytes":4543641400,"gc":[293,196,196],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7760,"sharedPasses":1940,"driverPasses":1940,"browserPasses":1940}
|
||||
{"cycle":980,"elapsedSeconds":1305.1370692,"utc":"2026-11-10T18:06:30.2607127Z","WorkingSet64":139743232,"PrivateMemorySize64":246317056,"managedBytes":4644840,"allocatedBytes":4590341832,"gc":[296,198,198],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7840,"sharedPasses":1960,"driverPasses":1960,"browserPasses":1960}
|
||||
{"cycle":990,"elapsedSeconds":1318.5113041,"utc":"2026-11-10T18:06:43.6340267Z","WorkingSet64":139743232,"PrivateMemorySize64":246317056,"managedBytes":4644672,"allocatedBytes":4637044696,"gc":[299,200,200],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":7920,"sharedPasses":1980,"driverPasses":1980,"browserPasses":1980}
|
||||
{"cycle":1000,"elapsedSeconds":1331.8291343,"utc":"2026-11-10T18:06:56.9531769Z","WorkingSet64":145399808,"PrivateMemorySize64":246841344,"managedBytes":4655328,"allocatedBytes":4683910576,"gc":[302,202,202],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8000,"sharedPasses":2000,"driverPasses":2000,"browserPasses":2000}
|
||||
{"cycle":1010,"elapsedSeconds":1346.5536167,"utc":"2026-11-10T18:07:11.6758977Z","WorkingSet64":142626816,"PrivateMemorySize64":246841344,"managedBytes":4720744,"allocatedBytes":4730691520,"gc":[305,204,204],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8080,"sharedPasses":2020,"driverPasses":2020,"browserPasses":2020}
|
||||
{"cycle":1020,"elapsedSeconds":1359.7287206,"utc":"2026-11-10T18:07:24.8528482Z","WorkingSet64":143069184,"PrivateMemorySize64":255459328,"managedBytes":4744384,"allocatedBytes":4777455496,"gc":[308,206,206],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8160,"sharedPasses":2040,"driverPasses":2040,"browserPasses":2040}
|
||||
{"cycle":1030,"elapsedSeconds":1373.0594056,"utc":"2026-11-10T18:07:38.179103Z","WorkingSet64":143056896,"PrivateMemorySize64":247009280,"managedBytes":4516048,"allocatedBytes":4824197776,"gc":[311,208,208],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8240,"sharedPasses":2060,"driverPasses":2060,"browserPasses":2060}
|
||||
{"cycle":1040,"elapsedSeconds":1386.3945337,"utc":"2026-11-10T18:07:51.5392663Z","WorkingSet64":141619200,"PrivateMemorySize64":247029760,"managedBytes":4581064,"allocatedBytes":4870989312,"gc":[314,210,210],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8320,"sharedPasses":2080,"driverPasses":2080,"browserPasses":2080}
|
||||
{"cycle":1050,"elapsedSeconds":1399.7240136,"utc":"2026-11-10T18:08:04.8487418Z","WorkingSet64":141619200,"PrivateMemorySize64":247009280,"managedBytes":4516312,"allocatedBytes":4917708640,"gc":[317,212,212],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8400,"sharedPasses":2100,"driverPasses":2100,"browserPasses":2100}
|
||||
{"cycle":1060,"elapsedSeconds":1414.4014588,"utc":"2026-11-10T18:08:19.5229664Z","WorkingSet64":141619200,"PrivateMemorySize64":247029760,"managedBytes":4646848,"allocatedBytes":4964536176,"gc":[320,214,214],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8480,"sharedPasses":2120,"driverPasses":2120,"browserPasses":2120}
|
||||
{"cycle":1070,"elapsedSeconds":1427.7593602,"utc":"2026-11-10T18:08:32.8823181Z","WorkingSet64":138493952,"PrivateMemorySize64":247029760,"managedBytes":4647848,"allocatedBytes":5011244288,"gc":[323,216,216],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8560,"sharedPasses":2140,"driverPasses":2140,"browserPasses":2140}
|
||||
{"cycle":1080,"elapsedSeconds":1441.1025344,"utc":"2026-11-10T18:08:46.2275674Z","WorkingSet64":138579968,"PrivateMemorySize64":247029760,"managedBytes":4629840,"allocatedBytes":5057967016,"gc":[326,218,218],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8640,"sharedPasses":2160,"driverPasses":2160,"browserPasses":2160}
|
||||
{"cycle":1090,"elapsedSeconds":1454.4184261,"utc":"2026-11-10T18:08:59.5424563Z","WorkingSet64":138579968,"PrivateMemorySize64":247029760,"managedBytes":4514248,"allocatedBytes":5104663168,"gc":[329,220,220],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8720,"sharedPasses":2180,"driverPasses":2180,"browserPasses":2180}
|
||||
{"cycle":1100,"elapsedSeconds":1467.7018179,"utc":"2026-11-10T18:09:12.819323Z","WorkingSet64":140947456,"PrivateMemorySize64":247029760,"managedBytes":4565624,"allocatedBytes":5151409632,"gc":[332,222,222],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8800,"sharedPasses":2200,"driverPasses":2200,"browserPasses":2200}
|
||||
{"cycle":1110,"elapsedSeconds":1481.0477388,"utc":"2026-11-10T18:09:26.1698485Z","WorkingSet64":137891840,"PrivateMemorySize64":247029760,"managedBytes":4630816,"allocatedBytes":5198224288,"gc":[335,224,224],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8880,"sharedPasses":2220,"driverPasses":2220,"browserPasses":2220}
|
||||
{"cycle":1120,"elapsedSeconds":1494.3852703,"utc":"2026-11-10T18:09:39.5051633Z","WorkingSet64":137891840,"PrivateMemorySize64":247029760,"managedBytes":4517056,"allocatedBytes":5244950888,"gc":[338,226,226],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":8960,"sharedPasses":2240,"driverPasses":2240,"browserPasses":2240}
|
||||
{"cycle":1130,"elapsedSeconds":1507.7647938,"utc":"2026-11-10T18:09:52.885106Z","WorkingSet64":138997760,"PrivateMemorySize64":247029760,"managedBytes":4650240,"allocatedBytes":5292768256,"gc":[341,228,228],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9040,"sharedPasses":2260,"driverPasses":2260,"browserPasses":2260}
|
||||
{"cycle":1140,"elapsedSeconds":1521.0713321,"utc":"2026-11-10T18:10:06.1916721Z","WorkingSet64":137912320,"PrivateMemorySize64":247029760,"managedBytes":4509544,"allocatedBytes":5339450904,"gc":[344,230,230],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9120,"sharedPasses":2280,"driverPasses":2280,"browserPasses":2280}
|
||||
{"cycle":1150,"elapsedSeconds":1534.435738,"utc":"2026-11-10T18:10:19.5605195Z","WorkingSet64":138235904,"PrivateMemorySize64":247009280,"managedBytes":4516472,"allocatedBytes":5386173568,"gc":[347,232,232],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9200,"sharedPasses":2300,"driverPasses":2300,"browserPasses":2300}
|
||||
{"cycle":1160,"elapsedSeconds":1547.5446634,"utc":"2026-11-10T18:10:32.6620821Z","WorkingSet64":138452992,"PrivateMemorySize64":247009280,"managedBytes":4508384,"allocatedBytes":5432887232,"gc":[350,234,234],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9280,"sharedPasses":2320,"driverPasses":2320,"browserPasses":2320}
|
||||
{"cycle":1170,"elapsedSeconds":1560.888704,"utc":"2026-11-10T18:10:46.0179428Z","WorkingSet64":138399744,"PrivateMemorySize64":247029760,"managedBytes":4630488,"allocatedBytes":5479735384,"gc":[353,236,236],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9360,"sharedPasses":2340,"driverPasses":2340,"browserPasses":2340}
|
||||
{"cycle":1180,"elapsedSeconds":1574.2072805,"utc":"2026-11-10T18:10:59.3255877Z","WorkingSet64":138596352,"PrivateMemorySize64":247029760,"managedBytes":4631992,"allocatedBytes":5526436568,"gc":[356,238,238],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9440,"sharedPasses":2360,"driverPasses":2360,"browserPasses":2360}
|
||||
{"cycle":1190,"elapsedSeconds":1587.5311377,"utc":"2026-11-10T18:11:12.6501734Z","WorkingSet64":139821056,"PrivateMemorySize64":247009280,"managedBytes":4516296,"allocatedBytes":5573144160,"gc":[359,240,240],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9520,"sharedPasses":2380,"driverPasses":2380,"browserPasses":2380}
|
||||
{"cycle":1200,"elapsedSeconds":1600.8550938,"utc":"2026-11-10T18:11:25.9739753Z","WorkingSet64":139821056,"PrivateMemorySize64":247009280,"managedBytes":4516664,"allocatedBytes":5619855784,"gc":[362,242,242],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9600,"sharedPasses":2400,"driverPasses":2400,"browserPasses":2400}
|
||||
{"cycle":1210,"elapsedSeconds":1614.1373595,"utc":"2026-11-10T18:11:39.2552215Z","WorkingSet64":137674752,"PrivateMemorySize64":247136256,"managedBytes":4736656,"allocatedBytes":5666803624,"gc":[365,244,244],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9680,"sharedPasses":2420,"driverPasses":2420,"browserPasses":2420}
|
||||
{"cycle":1220,"elapsedSeconds":1627.4900653,"utc":"2026-11-10T18:11:52.6144638Z","WorkingSet64":137674752,"PrivateMemorySize64":247074816,"managedBytes":4516624,"allocatedBytes":5713537352,"gc":[368,246,246],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9760,"sharedPasses":2440,"driverPasses":2440,"browserPasses":2440}
|
||||
{"cycle":1230,"elapsedSeconds":1640.8110675,"utc":"2026-11-10T18:12:05.9285163Z","WorkingSet64":137711616,"PrivateMemorySize64":247074816,"managedBytes":4516928,"allocatedBytes":5760231648,"gc":[371,248,248],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9840,"sharedPasses":2460,"driverPasses":2460,"browserPasses":2460}
|
||||
{"cycle":1240,"elapsedSeconds":1654.1099118,"utc":"2026-11-10T18:12:19.2306735Z","WorkingSet64":136536064,"PrivateMemorySize64":247095296,"managedBytes":4574048,"allocatedBytes":5806975552,"gc":[374,250,250],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":9920,"sharedPasses":2480,"driverPasses":2480,"browserPasses":2480}
|
||||
{"cycle":1250,"elapsedSeconds":1667.3634254,"utc":"2026-11-10T18:12:32.4815789Z","WorkingSet64":136585216,"PrivateMemorySize64":247095296,"managedBytes":4564816,"allocatedBytes":5853684944,"gc":[377,252,252],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10000,"sharedPasses":2500,"driverPasses":2500,"browserPasses":2500}
|
||||
{"cycle":1260,"elapsedSeconds":1680.6600475,"utc":"2026-11-10T18:12:45.7831188Z","WorkingSet64":137273344,"PrivateMemorySize64":247115776,"managedBytes":4530104,"allocatedBytes":5900390488,"gc":[380,254,254],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10080,"sharedPasses":2520,"driverPasses":2520,"browserPasses":2520}
|
||||
{"cycle":1270,"elapsedSeconds":1693.9695244,"utc":"2026-11-10T18:12:59.095321Z","WorkingSet64":137273344,"PrivateMemorySize64":247095296,"managedBytes":4556272,"allocatedBytes":5947116888,"gc":[383,256,256],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10160,"sharedPasses":2540,"driverPasses":2540,"browserPasses":2540}
|
||||
{"cycle":1280,"elapsedSeconds":1707.2398061,"utc":"2026-11-10T18:13:12.3625522Z","WorkingSet64":137027584,"PrivateMemorySize64":247095296,"managedBytes":4647376,"allocatedBytes":5993901016,"gc":[386,258,258],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10240,"sharedPasses":2560,"driverPasses":2560,"browserPasses":2560}
|
||||
{"cycle":1290,"elapsedSeconds":1720.5002753,"utc":"2026-11-10T18:13:25.6278775Z","WorkingSet64":137027584,"PrivateMemorySize64":247095296,"managedBytes":4646368,"allocatedBytes":6040626600,"gc":[389,260,260],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10320,"sharedPasses":2580,"driverPasses":2580,"browserPasses":2580}
|
||||
{"cycle":1300,"elapsedSeconds":1733.7836483,"utc":"2026-11-10T18:13:38.9012015Z","WorkingSet64":138080256,"PrivateMemorySize64":247095296,"managedBytes":4630144,"allocatedBytes":6087350664,"gc":[392,262,262],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10400,"sharedPasses":2600,"driverPasses":2600,"browserPasses":2600}
|
||||
{"cycle":1310,"elapsedSeconds":1747.1154746,"utc":"2026-11-10T18:13:52.2332268Z","WorkingSet64":136679424,"PrivateMemorySize64":247095296,"managedBytes":4538432,"allocatedBytes":6134076880,"gc":[395,264,264],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10480,"sharedPasses":2620,"driverPasses":2620,"browserPasses":2620}
|
||||
{"cycle":1320,"elapsedSeconds":1760.4065997,"utc":"2026-11-10T18:14:05.5242815Z","WorkingSet64":136843264,"PrivateMemorySize64":247095296,"managedBytes":4648144,"allocatedBytes":6180893088,"gc":[398,266,266],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10560,"sharedPasses":2640,"driverPasses":2640,"browserPasses":2640}
|
||||
{"cycle":1330,"elapsedSeconds":1773.5803288,"utc":"2026-11-10T18:14:18.7020362Z","WorkingSet64":136957952,"PrivateMemorySize64":247095296,"managedBytes":4631176,"allocatedBytes":6227619776,"gc":[401,268,268],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10640,"sharedPasses":2660,"driverPasses":2660,"browserPasses":2660}
|
||||
{"cycle":1340,"elapsedSeconds":1786.9233177,"utc":"2026-11-10T18:14:32.0412017Z","WorkingSet64":136998912,"PrivateMemorySize64":247095296,"managedBytes":4522856,"allocatedBytes":6274339168,"gc":[404,270,270],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10720,"sharedPasses":2680,"driverPasses":2680,"browserPasses":2680}
|
||||
{"cycle":1350,"elapsedSeconds":1800.2281551,"utc":"2026-11-10T18:14:45.3512335Z","WorkingSet64":137056256,"PrivateMemorySize64":247095296,"managedBytes":4566328,"allocatedBytes":6321085872,"gc":[407,272,272],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10800,"sharedPasses":2700,"driverPasses":2700,"browserPasses":2700}
|
||||
{"cycle":1360,"elapsedSeconds":1813.5769478,"utc":"2026-11-10T18:14:58.6947676Z","WorkingSet64":138088448,"PrivateMemorySize64":247095296,"managedBytes":4638440,"allocatedBytes":6368827328,"gc":[410,274,274],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10880,"sharedPasses":2720,"driverPasses":2720,"browserPasses":2720}
|
||||
{"cycle":1370,"elapsedSeconds":1826.8670103,"utc":"2026-11-10T18:15:11.990283Z","WorkingSet64":138088448,"PrivateMemorySize64":247074816,"managedBytes":4516656,"allocatedBytes":6415549376,"gc":[413,276,276],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":10960,"sharedPasses":2740,"driverPasses":2740,"browserPasses":2740}
|
||||
{"cycle":1380,"elapsedSeconds":1840.3092567,"utc":"2026-11-10T18:15:25.4338969Z","WorkingSet64":136617984,"PrivateMemorySize64":247074816,"managedBytes":4517688,"allocatedBytes":6462240480,"gc":[416,278,278],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11040,"sharedPasses":2760,"driverPasses":2760,"browserPasses":2760}
|
||||
{"cycle":1390,"elapsedSeconds":1853.9394438,"utc":"2026-11-10T18:15:39.0664869Z","WorkingSet64":136683520,"PrivateMemorySize64":247115776,"managedBytes":4720288,"allocatedBytes":6509119544,"gc":[419,280,280],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11120,"sharedPasses":2780,"driverPasses":2780,"browserPasses":2780}
|
||||
{"cycle":1400,"elapsedSeconds":1867.2304519,"utc":"2026-11-10T18:15:52.3545296Z","WorkingSet64":136683520,"PrivateMemorySize64":247095296,"managedBytes":4565472,"allocatedBytes":6555810712,"gc":[422,282,282],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11200,"sharedPasses":2800,"driverPasses":2800,"browserPasses":2800}
|
||||
{"cycle":1410,"elapsedSeconds":1880.5473124,"utc":"2026-11-10T18:16:05.6704664Z","WorkingSet64":136499200,"PrivateMemorySize64":247095296,"managedBytes":4517688,"allocatedBytes":6602519160,"gc":[425,284,284],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11280,"sharedPasses":2820,"driverPasses":2820,"browserPasses":2820}
|
||||
{"cycle":1420,"elapsedSeconds":1893.8702526,"utc":"2026-11-10T18:16:18.9954993Z","WorkingSet64":136552448,"PrivateMemorySize64":247095296,"managedBytes":4631536,"allocatedBytes":6649345896,"gc":[428,286,286],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11360,"sharedPasses":2840,"driverPasses":2840,"browserPasses":2840}
|
||||
{"cycle":1430,"elapsedSeconds":1907.146463,"utc":"2026-11-10T18:16:32.2737756Z","WorkingSet64":136560640,"PrivateMemorySize64":247095296,"managedBytes":4631424,"allocatedBytes":6696047192,"gc":[431,288,288],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11440,"sharedPasses":2860,"driverPasses":2860,"browserPasses":2860}
|
||||
{"cycle":1440,"elapsedSeconds":1920.4070682,"utc":"2026-11-10T18:16:45.5295848Z","WorkingSet64":134692864,"PrivateMemorySize64":247115776,"managedBytes":4655832,"allocatedBytes":6742830296,"gc":[434,290,290],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11520,"sharedPasses":2880,"driverPasses":2880,"browserPasses":2880}
|
||||
{"cycle":1450,"elapsedSeconds":1933.6768004,"utc":"2026-11-10T18:16:58.7942646Z","WorkingSet64":134692864,"PrivateMemorySize64":247115776,"managedBytes":4621528,"allocatedBytes":6789528608,"gc":[437,292,292],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11600,"sharedPasses":2900,"driverPasses":2900,"browserPasses":2900}
|
||||
{"cycle":1460,"elapsedSeconds":1946.8110388,"utc":"2026-11-10T18:17:11.935328Z","WorkingSet64":137175040,"PrivateMemorySize64":247136256,"managedBytes":4596816,"allocatedBytes":6836289016,"gc":[440,294,294],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11680,"sharedPasses":2920,"driverPasses":2920,"browserPasses":2920}
|
||||
{"cycle":1470,"elapsedSeconds":1960.2422696,"utc":"2026-11-10T18:17:25.3601895Z","WorkingSet64":137175040,"PrivateMemorySize64":247095296,"managedBytes":4580840,"allocatedBytes":6882995992,"gc":[443,296,296],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11760,"sharedPasses":2940,"driverPasses":2940,"browserPasses":2940}
|
||||
{"cycle":1480,"elapsedSeconds":1973.4582607,"utc":"2026-11-10T18:17:38.5772935Z","WorkingSet64":137056256,"PrivateMemorySize64":247074816,"managedBytes":4516656,"allocatedBytes":6929697568,"gc":[446,298,298],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11840,"sharedPasses":2960,"driverPasses":2960,"browserPasses":2960}
|
||||
{"cycle":1490,"elapsedSeconds":1986.7176141,"utc":"2026-11-10T18:17:51.8424507Z","WorkingSet64":138252288,"PrivateMemorySize64":247095296,"managedBytes":4565920,"allocatedBytes":6976443296,"gc":[449,300,300],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":11920,"sharedPasses":2980,"driverPasses":2980,"browserPasses":2980}
|
||||
{"cycle":1500,"elapsedSeconds":1999.9966044,"utc":"2026-11-10T18:18:05.1254937Z","WorkingSet64":138428416,"PrivateMemorySize64":247095296,"managedBytes":4549504,"allocatedBytes":7023142600,"gc":[452,302,302],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12000,"sharedPasses":3000,"driverPasses":3000,"browserPasses":3000}
|
||||
{"cycle":1510,"elapsedSeconds":2013.2249533,"utc":"2026-11-10T18:18:18.3471073Z","WorkingSet64":137465856,"PrivateMemorySize64":247074816,"managedBytes":4508888,"allocatedBytes":7069864088,"gc":[455,304,304],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12080,"sharedPasses":3020,"driverPasses":3020,"browserPasses":3020}
|
||||
{"cycle":1520,"elapsedSeconds":2026.4953922,"utc":"2026-11-10T18:18:31.6147466Z","WorkingSet64":138018816,"PrivateMemorySize64":247095296,"managedBytes":4646720,"allocatedBytes":7116708424,"gc":[458,306,306],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12160,"sharedPasses":3040,"driverPasses":3040,"browserPasses":3040}
|
||||
{"cycle":1530,"elapsedSeconds":2039.7154802,"utc":"2026-11-10T18:18:44.8355938Z","WorkingSet64":138018816,"PrivateMemorySize64":247115776,"managedBytes":4639832,"allocatedBytes":7163431624,"gc":[461,308,308],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12240,"sharedPasses":3060,"driverPasses":3060,"browserPasses":3060}
|
||||
{"cycle":1540,"elapsedSeconds":2052.9307959,"utc":"2026-11-10T18:18:58.048379Z","WorkingSet64":138080256,"PrivateMemorySize64":247115776,"managedBytes":4596336,"allocatedBytes":7210151480,"gc":[464,310,310],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12320,"sharedPasses":3080,"driverPasses":3080,"browserPasses":3080}
|
||||
{"cycle":1550,"elapsedSeconds":2066.1629511,"utc":"2026-11-10T18:19:11.2861941Z","WorkingSet64":136790016,"PrivateMemorySize64":247074816,"managedBytes":4582816,"allocatedBytes":7256841728,"gc":[467,312,312],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12400,"sharedPasses":3100,"driverPasses":3100,"browserPasses":3100}
|
||||
{"cycle":1560,"elapsedSeconds":2079.2794502,"utc":"2026-11-10T18:19:24.398575Z","WorkingSet64":136790016,"PrivateMemorySize64":247074816,"managedBytes":4582712,"allocatedBytes":7303526936,"gc":[470,314,314],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12480,"sharedPasses":3120,"driverPasses":3120,"browserPasses":3120}
|
||||
{"cycle":1570,"elapsedSeconds":2092.5482995,"utc":"2026-11-10T18:19:37.6719344Z","WorkingSet64":136790016,"PrivateMemorySize64":247074816,"managedBytes":4583824,"allocatedBytes":7350219296,"gc":[473,316,316],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12560,"sharedPasses":3140,"driverPasses":3140,"browserPasses":3140}
|
||||
{"cycle":1580,"elapsedSeconds":2105.8147467,"utc":"2026-11-10T18:19:50.9423122Z","WorkingSet64":139313152,"PrivateMemorySize64":247074816,"managedBytes":4582048,"allocatedBytes":7397889688,"gc":[476,318,318],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12640,"sharedPasses":3160,"driverPasses":3160,"browserPasses":3160}
|
||||
{"cycle":1590,"elapsedSeconds":2119.0615168,"utc":"2026-11-10T18:20:04.1819379Z","WorkingSet64":139313152,"PrivateMemorySize64":247074816,"managedBytes":4582016,"allocatedBytes":7444610984,"gc":[479,320,320],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12720,"sharedPasses":3180,"driverPasses":3180,"browserPasses":3180}
|
||||
{"cycle":1600,"elapsedSeconds":2132.293745,"utc":"2026-11-10T18:20:17.4119578Z","WorkingSet64":139325440,"PrivateMemorySize64":247095296,"managedBytes":4614896,"allocatedBytes":7491375976,"gc":[482,322,322],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12800,"sharedPasses":3200,"driverPasses":3200,"browserPasses":3200}
|
||||
{"cycle":1610,"elapsedSeconds":2145.5361456,"utc":"2026-11-10T18:20:30.6539337Z","WorkingSet64":138514432,"PrivateMemorySize64":247095296,"managedBytes":4647528,"allocatedBytes":7538120008,"gc":[485,324,324],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12880,"sharedPasses":3220,"driverPasses":3220,"browserPasses":3220}
|
||||
{"cycle":1620,"elapsedSeconds":2158.737018,"utc":"2026-11-10T18:20:43.8589913Z","WorkingSet64":138514432,"PrivateMemorySize64":247095296,"managedBytes":4647592,"allocatedBytes":7584840152,"gc":[488,326,326],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":12960,"sharedPasses":3240,"driverPasses":3240,"browserPasses":3240}
|
||||
{"cycle":1630,"elapsedSeconds":2171.8600863,"utc":"2026-11-10T18:20:56.9811391Z","WorkingSet64":138514432,"PrivateMemorySize64":247095296,"managedBytes":4631144,"allocatedBytes":7631578368,"gc":[491,328,328],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13040,"sharedPasses":3260,"driverPasses":3260,"browserPasses":3260}
|
||||
{"cycle":1640,"elapsedSeconds":2185.1105072,"utc":"2026-11-10T18:21:10.2337275Z","WorkingSet64":138829824,"PrivateMemorySize64":247115776,"managedBytes":4639544,"allocatedBytes":7678288784,"gc":[494,330,330],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13120,"sharedPasses":3280,"driverPasses":3280,"browserPasses":3280}
|
||||
{"cycle":1650,"elapsedSeconds":2198.3165558,"utc":"2026-11-10T18:21:23.4452832Z","WorkingSet64":137834496,"PrivateMemorySize64":247095296,"managedBytes":4630216,"allocatedBytes":7724967608,"gc":[497,332,332],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13200,"sharedPasses":3300,"driverPasses":3300,"browserPasses":3300}
|
||||
{"cycle":1660,"elapsedSeconds":2211.5554794,"utc":"2026-11-10T18:21:36.6819109Z","WorkingSet64":137834496,"PrivateMemorySize64":247095296,"managedBytes":4630472,"allocatedBytes":7771680552,"gc":[500,334,334],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13280,"sharedPasses":3320,"driverPasses":3320,"browserPasses":3320}
|
||||
{"cycle":1670,"elapsedSeconds":2224.7569182,"utc":"2026-11-10T18:21:49.8838303Z","WorkingSet64":137834496,"PrivateMemorySize64":247095296,"managedBytes":4648440,"allocatedBytes":7818418288,"gc":[503,336,336],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13360,"sharedPasses":3340,"driverPasses":3340,"browserPasses":3340}
|
||||
{"cycle":1680,"elapsedSeconds":2237.8689779,"utc":"2026-11-10T18:22:03.0006017Z","WorkingSet64":136896512,"PrivateMemorySize64":247095296,"managedBytes":4646680,"allocatedBytes":7865134736,"gc":[506,338,338],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13440,"sharedPasses":3360,"driverPasses":3360,"browserPasses":3360}
|
||||
{"cycle":1690,"elapsedSeconds":2251.1051878,"utc":"2026-11-10T18:22:16.2299041Z","WorkingSet64":136962048,"PrivateMemorySize64":247095296,"managedBytes":4630720,"allocatedBytes":7911833728,"gc":[509,340,340],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13520,"sharedPasses":3380,"driverPasses":3380,"browserPasses":3380}
|
||||
{"cycle":1700,"elapsedSeconds":2264.3999716,"utc":"2026-11-10T18:22:29.5239101Z","WorkingSet64":136962048,"PrivateMemorySize64":247095296,"managedBytes":4647160,"allocatedBytes":7958559744,"gc":[512,342,342],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13600,"sharedPasses":3400,"driverPasses":3400,"browserPasses":3400}
|
||||
{"cycle":1710,"elapsedSeconds":2277.6834886,"utc":"2026-11-10T18:22:42.8022829Z","WorkingSet64":137003008,"PrivateMemorySize64":247095296,"managedBytes":4647104,"allocatedBytes":8005274288,"gc":[515,344,344],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13680,"sharedPasses":3420,"driverPasses":3420,"browserPasses":3420}
|
||||
{"cycle":1720,"elapsedSeconds":2290.9457052,"utc":"2026-11-10T18:22:56.0743607Z","WorkingSet64":137302016,"PrivateMemorySize64":247115776,"managedBytes":4656016,"allocatedBytes":8051971648,"gc":[518,346,346],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13760,"sharedPasses":3440,"driverPasses":3440,"browserPasses":3440}
|
||||
{"cycle":1730,"elapsedSeconds":2304.2362097,"utc":"2026-11-10T18:23:09.3534475Z","WorkingSet64":137314304,"PrivateMemorySize64":247119872,"managedBytes":4647592,"allocatedBytes":8098675856,"gc":[521,348,348],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13840,"sharedPasses":3460,"driverPasses":3460,"browserPasses":3460}
|
||||
{"cycle":1740,"elapsedSeconds":2317.524939,"utc":"2026-11-10T18:23:22.6419748Z","WorkingSet64":137314304,"PrivateMemorySize64":247119872,"managedBytes":4647504,"allocatedBytes":8145511144,"gc":[524,350,350],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":13920,"sharedPasses":3480,"driverPasses":3480,"browserPasses":3480}
|
||||
{"cycle":1750,"elapsedSeconds":2330.8427595,"utc":"2026-11-10T18:23:35.9687964Z","WorkingSet64":135757824,"PrivateMemorySize64":247119872,"managedBytes":4646680,"allocatedBytes":8192212584,"gc":[527,352,352],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14000,"sharedPasses":3500,"driverPasses":3500,"browserPasses":3500}
|
||||
{"cycle":1760,"elapsedSeconds":2344.1646584,"utc":"2026-11-10T18:23:49.2885992Z","WorkingSet64":136843264,"PrivateMemorySize64":247119872,"managedBytes":4515968,"allocatedBytes":8238919152,"gc":[530,354,354],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14080,"sharedPasses":3520,"driverPasses":3520,"browserPasses":3520}
|
||||
{"cycle":1770,"elapsedSeconds":2357.53567,"utc":"2026-11-10T18:24:02.6642915Z","WorkingSet64":136843264,"PrivateMemorySize64":247099392,"managedBytes":4500584,"allocatedBytes":8285601912,"gc":[533,356,356],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14160,"sharedPasses":3540,"driverPasses":3540,"browserPasses":3540}
|
||||
{"cycle":1780,"elapsedSeconds":2370.832052,"utc":"2026-11-10T18:24:15.9519118Z","WorkingSet64":136511488,"PrivateMemorySize64":247119872,"managedBytes":4614720,"allocatedBytes":8332417608,"gc":[536,358,358],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14240,"sharedPasses":3560,"driverPasses":3560,"browserPasses":3560}
|
||||
{"cycle":1790,"elapsedSeconds":2384.0386193,"utc":"2026-11-10T18:24:29.1629364Z","WorkingSet64":136511488,"PrivateMemorySize64":247119872,"managedBytes":4631640,"allocatedBytes":8379137872,"gc":[539,360,360],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14320,"sharedPasses":3580,"driverPasses":3580,"browserPasses":3580}
|
||||
{"cycle":1800,"elapsedSeconds":2397.3494585,"utc":"2026-11-10T18:24:42.4747031Z","WorkingSet64":136511488,"PrivateMemorySize64":247119872,"managedBytes":4520824,"allocatedBytes":8425838320,"gc":[542,362,362],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14400,"sharedPasses":3600,"driverPasses":3600,"browserPasses":3600}
|
||||
{"cycle":1810,"elapsedSeconds":2410.699165,"utc":"2026-11-10T18:24:55.8166934Z","WorkingSet64":138088448,"PrivateMemorySize64":247787520,"managedBytes":4522072,"allocatedBytes":8473495664,"gc":[545,364,364],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14480,"sharedPasses":3620,"driverPasses":3620,"browserPasses":3620}
|
||||
{"cycle":1820,"elapsedSeconds":2424.0325256,"utc":"2026-11-10T18:25:09.1499308Z","WorkingSet64":136626176,"PrivateMemorySize64":247787520,"managedBytes":4624928,"allocatedBytes":8520306600,"gc":[548,366,366],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14560,"sharedPasses":3640,"driverPasses":3640,"browserPasses":3640}
|
||||
{"cycle":1830,"elapsedSeconds":2437.1159714,"utc":"2026-11-10T18:25:22.2332942Z","WorkingSet64":137408512,"PrivateMemorySize64":247787520,"managedBytes":4640544,"allocatedBytes":8567007904,"gc":[551,368,368],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14640,"sharedPasses":3660,"driverPasses":3660,"browserPasses":3660}
|
||||
{"cycle":1840,"elapsedSeconds":2450.4753988,"utc":"2026-11-10T18:25:35.6000775Z","WorkingSet64":137519104,"PrivateMemorySize64":247808000,"managedBytes":4655224,"allocatedBytes":8613728360,"gc":[554,370,370],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14720,"sharedPasses":3680,"driverPasses":3680,"browserPasses":3680}
|
||||
{"cycle":1850,"elapsedSeconds":2463.8130385,"utc":"2026-11-10T18:25:48.9359084Z","WorkingSet64":137895936,"PrivateMemorySize64":247767040,"managedBytes":4516904,"allocatedBytes":8660447192,"gc":[557,372,372],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14800,"sharedPasses":3700,"driverPasses":3700,"browserPasses":3700}
|
||||
{"cycle":1860,"elapsedSeconds":2477.0625223,"utc":"2026-11-10T18:26:02.1885177Z","WorkingSet64":137990144,"PrivateMemorySize64":247787520,"managedBytes":4581728,"allocatedBytes":8707236648,"gc":[560,374,374],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14880,"sharedPasses":3720,"driverPasses":3720,"browserPasses":3720}
|
||||
{"cycle":1870,"elapsedSeconds":2490.4390181,"utc":"2026-11-10T18:26:15.5674593Z","WorkingSet64":137990144,"PrivateMemorySize64":247787520,"managedBytes":4630152,"allocatedBytes":8753998360,"gc":[563,376,376],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":14960,"sharedPasses":3740,"driverPasses":3740,"browserPasses":3740}
|
||||
{"cycle":1880,"elapsedSeconds":2503.7854531,"utc":"2026-11-10T18:26:28.9025999Z","WorkingSet64":138797056,"PrivateMemorySize64":247787520,"managedBytes":4639424,"allocatedBytes":8800701288,"gc":[566,378,378],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15040,"sharedPasses":3760,"driverPasses":3760,"browserPasses":3760}
|
||||
{"cycle":1890,"elapsedSeconds":2517.0796801,"utc":"2026-11-10T18:26:42.2012909Z","WorkingSet64":138649600,"PrivateMemorySize64":247787520,"managedBytes":4646672,"allocatedBytes":8847401880,"gc":[569,380,380],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15120,"sharedPasses":3780,"driverPasses":3780,"browserPasses":3780}
|
||||
{"cycle":1900,"elapsedSeconds":2530.4471528,"utc":"2026-11-10T18:26:55.5646282Z","WorkingSet64":138711040,"PrivateMemorySize64":247767040,"managedBytes":4582280,"allocatedBytes":8894102608,"gc":[572,382,382],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15200,"sharedPasses":3800,"driverPasses":3800,"browserPasses":3800}
|
||||
{"cycle":1910,"elapsedSeconds":2543.804551,"utc":"2026-11-10T18:27:08.9219429Z","WorkingSet64":138711040,"PrivateMemorySize64":247787520,"managedBytes":4649488,"allocatedBytes":8940861936,"gc":[575,384,384],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15280,"sharedPasses":3820,"driverPasses":3820,"browserPasses":3820}
|
||||
{"cycle":1920,"elapsedSeconds":2557.1152703,"utc":"2026-11-10T18:27:22.2374334Z","WorkingSet64":138645504,"PrivateMemorySize64":247767040,"managedBytes":4582824,"allocatedBytes":8987563808,"gc":[578,386,386],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15360,"sharedPasses":3840,"driverPasses":3840,"browserPasses":3840}
|
||||
{"cycle":1930,"elapsedSeconds":2570.4020941,"utc":"2026-11-10T18:27:35.5302264Z","WorkingSet64":138645504,"PrivateMemorySize64":247787520,"managedBytes":4646376,"allocatedBytes":9034315952,"gc":[581,388,388],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15440,"sharedPasses":3860,"driverPasses":3860,"browserPasses":3860}
|
||||
{"cycle":1940,"elapsedSeconds":2583.7163414,"utc":"2026-11-10T18:27:48.8370152Z","WorkingSet64":138711040,"PrivateMemorySize64":247808000,"managedBytes":4637640,"allocatedBytes":9081049264,"gc":[584,390,390],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15520,"sharedPasses":3880,"driverPasses":3880,"browserPasses":3880}
|
||||
{"cycle":1950,"elapsedSeconds":2597.1614868,"utc":"2026-11-10T18:28:02.2907674Z","WorkingSet64":135892992,"PrivateMemorySize64":247787520,"managedBytes":4646624,"allocatedBytes":9127878592,"gc":[587,392,392],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15600,"sharedPasses":3900,"driverPasses":3900,"browserPasses":3900}
|
||||
{"cycle":1960,"elapsedSeconds":2610.5638849,"utc":"2026-11-10T18:28:15.6838969Z","WorkingSet64":135892992,"PrivateMemorySize64":247787520,"managedBytes":4646904,"allocatedBytes":9174566264,"gc":[590,394,394],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15680,"sharedPasses":3920,"driverPasses":3920,"browserPasses":3920}
|
||||
{"cycle":1970,"elapsedSeconds":2623.8831112,"utc":"2026-11-10T18:28:29.0093064Z","WorkingSet64":135892992,"PrivateMemorySize64":247787520,"managedBytes":4631608,"allocatedBytes":9221285464,"gc":[593,396,396],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15760,"sharedPasses":3940,"driverPasses":3940,"browserPasses":3940}
|
||||
{"cycle":1980,"elapsedSeconds":2637.2218407,"utc":"2026-11-10T18:28:42.3512126Z","WorkingSet64":135921664,"PrivateMemorySize64":247808000,"managedBytes":4703232,"allocatedBytes":9268046432,"gc":[596,398,398],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15840,"sharedPasses":3960,"driverPasses":3960,"browserPasses":3960}
|
||||
{"cycle":1990,"elapsedSeconds":2650.539745,"utc":"2026-11-10T18:28:55.6668257Z","WorkingSet64":135913472,"PrivateMemorySize64":247767040,"managedBytes":4581872,"allocatedBytes":9314781216,"gc":[599,400,400],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":15920,"sharedPasses":3980,"driverPasses":3980,"browserPasses":3980}
|
||||
{"cycle":2000,"elapsedSeconds":2663.8441782,"utc":"2026-11-10T18:29:08.9695541Z","WorkingSet64":135913472,"PrivateMemorySize64":247767040,"managedBytes":4582392,"allocatedBytes":9361474560,"gc":[602,402,402],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16000,"sharedPasses":4000,"driverPasses":4000,"browserPasses":4000}
|
||||
{"cycle":2010,"elapsedSeconds":2677.1740281,"utc":"2026-11-10T18:29:22.2948528Z","WorkingSet64":138665984,"PrivateMemorySize64":247808000,"managedBytes":4686240,"allocatedBytes":9408277472,"gc":[605,404,404],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16080,"sharedPasses":4020,"driverPasses":4020,"browserPasses":4020}
|
||||
{"cycle":2020,"elapsedSeconds":2690.4681673,"utc":"2026-11-10T18:29:35.5947545Z","WorkingSet64":137682944,"PrivateMemorySize64":247787520,"managedBytes":4630056,"allocatedBytes":9454979536,"gc":[608,406,406],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16160,"sharedPasses":4040,"driverPasses":4040,"browserPasses":4040}
|
||||
{"cycle":2030,"elapsedSeconds":2703.7962157,"utc":"2026-11-10T18:29:48.9258312Z","WorkingSet64":138342400,"PrivateMemorySize64":247951360,"managedBytes":4647752,"allocatedBytes":9502665528,"gc":[611,408,408],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16240,"sharedPasses":4060,"driverPasses":4060,"browserPasses":4060}
|
||||
{"cycle":2040,"elapsedSeconds":2717.1308802,"utc":"2026-11-10T18:30:02.2532544Z","WorkingSet64":138731520,"PrivateMemorySize64":248270848,"managedBytes":4521888,"allocatedBytes":9549349232,"gc":[614,410,410],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16320,"sharedPasses":4080,"driverPasses":4080,"browserPasses":4080}
|
||||
{"cycle":2050,"elapsedSeconds":2730.3370295,"utc":"2026-11-10T18:30:15.4646329Z","WorkingSet64":138731520,"PrivateMemorySize64":248270848,"managedBytes":4565408,"allocatedBytes":9596105064,"gc":[617,412,412],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16400,"sharedPasses":4100,"driverPasses":4100,"browserPasses":4100}
|
||||
{"cycle":2060,"elapsedSeconds":2743.6617215,"utc":"2026-11-10T18:30:28.7886336Z","WorkingSet64":138350592,"PrivateMemorySize64":248270848,"managedBytes":4581448,"allocatedBytes":9642823376,"gc":[620,414,414],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16480,"sharedPasses":4120,"driverPasses":4120,"browserPasses":4120}
|
||||
{"cycle":2070,"elapsedSeconds":2756.9877393,"utc":"2026-11-10T18:30:42.1124635Z","WorkingSet64":140828672,"PrivateMemorySize64":248291328,"managedBytes":4573664,"allocatedBytes":9689559584,"gc":[623,416,416],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16560,"sharedPasses":4140,"driverPasses":4140,"browserPasses":4140}
|
||||
{"cycle":2080,"elapsedSeconds":2770.3042485,"utc":"2026-11-10T18:30:55.429929Z","WorkingSet64":140828672,"PrivateMemorySize64":248270848,"managedBytes":4582080,"allocatedBytes":9736275368,"gc":[626,418,418],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16640,"sharedPasses":4160,"driverPasses":4160,"browserPasses":4160}
|
||||
{"cycle":2090,"elapsedSeconds":2783.6840022,"utc":"2026-11-10T18:31:08.8030717Z","WorkingSet64":140148736,"PrivateMemorySize64":248291328,"managedBytes":4564544,"allocatedBytes":9783022480,"gc":[629,420,420],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16720,"sharedPasses":4180,"driverPasses":4180,"browserPasses":4180}
|
||||
{"cycle":2100,"elapsedSeconds":2797.1979142,"utc":"2026-11-10T18:31:22.315798Z","WorkingSet64":140251136,"PrivateMemorySize64":248291328,"managedBytes":4778032,"allocatedBytes":9829933448,"gc":[632,422,422],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16800,"sharedPasses":4200,"driverPasses":4200,"browserPasses":4200}
|
||||
{"cycle":2110,"elapsedSeconds":2810.2095128,"utc":"2026-11-10T18:31:35.3268782Z","WorkingSet64":140251136,"PrivateMemorySize64":248270848,"managedBytes":4614528,"allocatedBytes":9876638648,"gc":[635,424,424],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16880,"sharedPasses":4220,"driverPasses":4220,"browserPasses":4220}
|
||||
{"cycle":2120,"elapsedSeconds":2823.4268007,"utc":"2026-11-10T18:31:48.5578323Z","WorkingSet64":139083776,"PrivateMemorySize64":248270848,"managedBytes":4522416,"allocatedBytes":9923346424,"gc":[638,426,426],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":16960,"sharedPasses":4240,"driverPasses":4240,"browserPasses":4240}
|
||||
{"cycle":2130,"elapsedSeconds":2836.7069192,"utc":"2026-11-10T18:32:01.8244195Z","WorkingSet64":139083776,"PrivateMemorySize64":248270848,"managedBytes":4514056,"allocatedBytes":9970035088,"gc":[641,428,428],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17040,"sharedPasses":4260,"driverPasses":4260,"browserPasses":4260}
|
||||
{"cycle":2140,"elapsedSeconds":2850.0267526,"utc":"2026-11-10T18:32:15.1454111Z","WorkingSet64":139657216,"PrivateMemorySize64":248270848,"managedBytes":4647824,"allocatedBytes":10016869552,"gc":[644,430,430],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17120,"sharedPasses":4280,"driverPasses":4280,"browserPasses":4280}
|
||||
{"cycle":2150,"elapsedSeconds":2863.3821078,"utc":"2026-11-10T18:32:28.5143232Z","WorkingSet64":139657216,"PrivateMemorySize64":248270848,"managedBytes":4631064,"allocatedBytes":10063589400,"gc":[647,432,432],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17200,"sharedPasses":4300,"driverPasses":4300,"browserPasses":4300}
|
||||
{"cycle":2160,"elapsedSeconds":2876.6553751,"utc":"2026-11-10T18:32:41.785683Z","WorkingSet64":139042816,"PrivateMemorySize64":248377344,"managedBytes":4752624,"allocatedBytes":10110429368,"gc":[650,434,434],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17280,"sharedPasses":4320,"driverPasses":4320,"browserPasses":4320}
|
||||
{"cycle":2170,"elapsedSeconds":2889.9759578,"utc":"2026-11-10T18:32:55.1026875Z","WorkingSet64":139096064,"PrivateMemorySize64":248356864,"managedBytes":4627528,"allocatedBytes":10157130152,"gc":[653,436,436],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17360,"sharedPasses":4340,"driverPasses":4340,"browserPasses":4340}
|
||||
{"cycle":2180,"elapsedSeconds":2903.2588842,"utc":"2026-11-10T18:33:08.3853269Z","WorkingSet64":139132928,"PrivateMemorySize64":248315904,"managedBytes":4516080,"allocatedBytes":10203887920,"gc":[656,438,438],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17440,"sharedPasses":4360,"driverPasses":4360,"browserPasses":4360}
|
||||
{"cycle":2190,"elapsedSeconds":2916.5802093,"utc":"2026-11-10T18:33:21.7089622Z","WorkingSet64":138510336,"PrivateMemorySize64":248336384,"managedBytes":4567544,"allocatedBytes":10250662816,"gc":[659,440,440],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17520,"sharedPasses":4380,"driverPasses":4380,"browserPasses":4380}
|
||||
{"cycle":2200,"elapsedSeconds":2929.8721086,"utc":"2026-11-10T18:33:34.9894493Z","WorkingSet64":138752000,"PrivateMemorySize64":248356864,"managedBytes":4558456,"allocatedBytes":10297378040,"gc":[662,442,442],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17600,"sharedPasses":4400,"driverPasses":4400,"browserPasses":4400}
|
||||
{"cycle":2210,"elapsedSeconds":2943.146189,"utc":"2026-11-10T18:33:48.2642691Z","WorkingSet64":138752000,"PrivateMemorySize64":248356864,"managedBytes":4657320,"allocatedBytes":10344182648,"gc":[665,444,444],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17680,"sharedPasses":4420,"driverPasses":4420,"browserPasses":4420}
|
||||
{"cycle":2220,"elapsedSeconds":2956.5000095,"utc":"2026-11-10T18:34:01.6211071Z","WorkingSet64":138293248,"PrivateMemorySize64":248356864,"managedBytes":4639480,"allocatedBytes":10390881776,"gc":[668,446,446],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17760,"sharedPasses":4440,"driverPasses":4440,"browserPasses":4440}
|
||||
{"cycle":2230,"elapsedSeconds":2969.8096515,"utc":"2026-11-10T18:34:14.927071Z","WorkingSet64":138350592,"PrivateMemorySize64":248356864,"managedBytes":4631056,"allocatedBytes":10437697368,"gc":[671,448,448],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17840,"sharedPasses":4460,"driverPasses":4460,"browserPasses":4460}
|
||||
{"cycle":2240,"elapsedSeconds":2983.0934272,"utc":"2026-11-10T18:34:28.2142358Z","WorkingSet64":139091968,"PrivateMemorySize64":248336384,"managedBytes":4647200,"allocatedBytes":10484410360,"gc":[674,450,450],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":17920,"sharedPasses":4480,"driverPasses":4480,"browserPasses":4480}
|
||||
{"cycle":2250,"elapsedSeconds":2996.4042566,"utc":"2026-11-10T18:34:41.5215897Z","WorkingSet64":139091968,"PrivateMemorySize64":248336384,"managedBytes":4655024,"allocatedBytes":10531117040,"gc":[677,452,452],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18000,"sharedPasses":4500,"driverPasses":4500,"browserPasses":4500}
|
||||
{"cycle":2260,"elapsedSeconds":3009.7364308,"utc":"2026-11-10T18:34:54.8647018Z","WorkingSet64":138768384,"PrivateMemorySize64":248336384,"managedBytes":4612304,"allocatedBytes":10578820008,"gc":[680,454,454],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18080,"sharedPasses":4520,"driverPasses":4520,"browserPasses":4520}
|
||||
{"cycle":2270,"elapsedSeconds":3022.8462638,"utc":"2026-11-10T18:35:07.9738308Z","WorkingSet64":138768384,"PrivateMemorySize64":248336384,"managedBytes":4648096,"allocatedBytes":10625559056,"gc":[683,456,456],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18160,"sharedPasses":4540,"driverPasses":4540,"browserPasses":4540}
|
||||
{"cycle":2280,"elapsedSeconds":3036.0239925,"utc":"2026-11-10T18:35:21.1526264Z","WorkingSet64":138768384,"PrivateMemorySize64":248336384,"managedBytes":4630864,"allocatedBytes":10672261504,"gc":[686,458,458],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18240,"sharedPasses":4560,"driverPasses":4560,"browserPasses":4560}
|
||||
{"cycle":2290,"elapsedSeconds":3049.3282305,"utc":"2026-11-10T18:35:34.4554672Z","WorkingSet64":138162176,"PrivateMemorySize64":248336384,"managedBytes":4630408,"allocatedBytes":10718984024,"gc":[689,460,460],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18320,"sharedPasses":4580,"driverPasses":4580,"browserPasses":4580}
|
||||
{"cycle":2300,"elapsedSeconds":3062.5922737,"utc":"2026-11-10T18:35:47.7102829Z","WorkingSet64":137940992,"PrivateMemorySize64":248016896,"managedBytes":4517768,"allocatedBytes":10765702000,"gc":[692,462,462],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18400,"sharedPasses":4600,"driverPasses":4600,"browserPasses":4600}
|
||||
{"cycle":2310,"elapsedSeconds":3075.7793947,"utc":"2026-11-10T18:36:00.9087939Z","WorkingSet64":137940992,"PrivateMemorySize64":248057856,"managedBytes":4527800,"allocatedBytes":10812416632,"gc":[695,464,464],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18480,"sharedPasses":4620,"driverPasses":4620,"browserPasses":4620}
|
||||
{"cycle":2320,"elapsedSeconds":3088.9913025,"utc":"2026-11-10T18:36:14.1172178Z","WorkingSet64":137940992,"PrivateMemorySize64":248057856,"managedBytes":4527464,"allocatedBytes":10859101352,"gc":[698,466,466],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18560,"sharedPasses":4640,"driverPasses":4640,"browserPasses":4640}
|
||||
{"cycle":2330,"elapsedSeconds":3102.197096,"utc":"2026-11-10T18:36:27.318052Z","WorkingSet64":137347072,"PrivateMemorySize64":248037376,"managedBytes":4585296,"allocatedBytes":10905852872,"gc":[701,468,468],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18640,"sharedPasses":4660,"driverPasses":4660,"browserPasses":4660}
|
||||
{"cycle":2340,"elapsedSeconds":3115.528955,"utc":"2026-11-10T18:36:40.6542961Z","WorkingSet64":137347072,"PrivateMemorySize64":248037376,"managedBytes":4584520,"allocatedBytes":10952547960,"gc":[704,470,470],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18720,"sharedPasses":4680,"driverPasses":4680,"browserPasses":4680}
|
||||
{"cycle":2350,"elapsedSeconds":3128.7993068,"utc":"2026-11-10T18:36:53.9276313Z","WorkingSet64":137347072,"PrivateMemorySize64":248037376,"managedBytes":4517728,"allocatedBytes":10999241048,"gc":[707,472,472],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18800,"sharedPasses":4700,"driverPasses":4700,"browserPasses":4700}
|
||||
{"cycle":2360,"elapsedSeconds":3142.0147934,"utc":"2026-11-10T18:37:07.1392823Z","WorkingSet64":136847360,"PrivateMemorySize64":248102912,"managedBytes":4630792,"allocatedBytes":11046066840,"gc":[710,474,474],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18880,"sharedPasses":4720,"driverPasses":4720,"browserPasses":4720}
|
||||
{"cycle":2370,"elapsedSeconds":3155.3268617,"utc":"2026-11-10T18:37:20.4513441Z","WorkingSet64":136847360,"PrivateMemorySize64":248082432,"managedBytes":4518040,"allocatedBytes":11092779112,"gc":[713,476,476],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":18960,"sharedPasses":4740,"driverPasses":4740,"browserPasses":4740}
|
||||
{"cycle":2380,"elapsedSeconds":3168.6958742,"utc":"2026-11-10T18:37:33.8136022Z","WorkingSet64":136847360,"PrivateMemorySize64":248082432,"managedBytes":4516928,"allocatedBytes":11139485768,"gc":[716,478,478],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19040,"sharedPasses":4760,"driverPasses":4760,"browserPasses":4760}
|
||||
{"cycle":2390,"elapsedSeconds":3182.0088761,"utc":"2026-11-10T18:37:47.1330212Z","WorkingSet64":137252864,"PrivateMemorySize64":248123392,"managedBytes":4526840,"allocatedBytes":11186207080,"gc":[719,480,480],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19120,"sharedPasses":4780,"driverPasses":4780,"browserPasses":4780}
|
||||
{"cycle":2400,"elapsedSeconds":3195.2878997,"utc":"2026-11-10T18:38:00.4059775Z","WorkingSet64":137252864,"PrivateMemorySize64":248102912,"managedBytes":4518696,"allocatedBytes":11232901168,"gc":[722,482,482],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19200,"sharedPasses":4800,"driverPasses":4800,"browserPasses":4800}
|
||||
{"cycle":2410,"elapsedSeconds":3208.5911344,"utc":"2026-11-10T18:38:13.7143472Z","WorkingSet64":137252864,"PrivateMemorySize64":248102912,"managedBytes":4612400,"allocatedBytes":11279705920,"gc":[725,484,484],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19280,"sharedPasses":4820,"driverPasses":4820,"browserPasses":4820}
|
||||
{"cycle":2420,"elapsedSeconds":3221.8951602,"utc":"2026-11-10T18:38:27.0202929Z","WorkingSet64":137252864,"PrivateMemorySize64":248102912,"managedBytes":4612560,"allocatedBytes":11326415640,"gc":[728,486,486],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19360,"sharedPasses":4840,"driverPasses":4840,"browserPasses":4840}
|
||||
{"cycle":2430,"elapsedSeconds":3235.2068821,"utc":"2026-11-10T18:38:40.331109Z","WorkingSet64":136732672,"PrivateMemorySize64":248082432,"managedBytes":4517400,"allocatedBytes":11373122848,"gc":[731,488,488],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19440,"sharedPasses":4860,"driverPasses":4860,"browserPasses":4860}
|
||||
{"cycle":2440,"elapsedSeconds":3248.5050924,"utc":"2026-11-10T18:38:53.6276319Z","WorkingSet64":136732672,"PrivateMemorySize64":248082432,"managedBytes":4517552,"allocatedBytes":11419821744,"gc":[734,490,490],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19520,"sharedPasses":4880,"driverPasses":4880,"browserPasses":4880}
|
||||
{"cycle":2450,"elapsedSeconds":3261.8383554,"utc":"2026-11-10T18:39:06.9569996Z","WorkingSet64":136732672,"PrivateMemorySize64":248102912,"managedBytes":4547296,"allocatedBytes":11466564480,"gc":[737,492,492],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19600,"sharedPasses":4900,"driverPasses":4900,"browserPasses":4900}
|
||||
{"cycle":2460,"elapsedSeconds":3275.1372908,"utc":"2026-11-10T18:39:20.2573743Z","WorkingSet64":136122368,"PrivateMemorySize64":248102912,"managedBytes":4565464,"allocatedBytes":11513291000,"gc":[740,494,494],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19680,"sharedPasses":4920,"driverPasses":4920,"browserPasses":4920}
|
||||
{"cycle":2470,"elapsedSeconds":3288.4283588,"utc":"2026-11-10T18:39:33.5565649Z","WorkingSet64":136122368,"PrivateMemorySize64":248082432,"managedBytes":4501120,"allocatedBytes":11559988256,"gc":[743,496,496],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19760,"sharedPasses":4940,"driverPasses":4940,"browserPasses":4940}
|
||||
{"cycle":2480,"elapsedSeconds":3301.7419796,"utc":"2026-11-10T18:39:46.8597078Z","WorkingSet64":136605696,"PrivateMemorySize64":248102912,"managedBytes":4557984,"allocatedBytes":11607734704,"gc":[746,498,498],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19840,"sharedPasses":4960,"driverPasses":4960,"browserPasses":4960}
|
||||
{"cycle":2490,"elapsedSeconds":3314.9103339,"utc":"2026-11-10T18:40:00.0284253Z","WorkingSet64":136785920,"PrivateMemorySize64":248102912,"managedBytes":4646888,"allocatedBytes":11654534784,"gc":[749,500,500],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":19920,"sharedPasses":4980,"driverPasses":4980,"browserPasses":4980}
|
||||
{"cycle":2500,"elapsedSeconds":3328.1766942,"utc":"2026-11-10T18:40:13.3055287Z","WorkingSet64":135938048,"PrivateMemorySize64":248102912,"managedBytes":4629880,"allocatedBytes":11701253648,"gc":[752,502,502],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20000,"sharedPasses":5000,"driverPasses":5000,"browserPasses":5000}
|
||||
{"cycle":2510,"elapsedSeconds":3341.3479978,"utc":"2026-11-10T18:40:26.4668782Z","WorkingSet64":135938048,"PrivateMemorySize64":248082432,"managedBytes":4517248,"allocatedBytes":11747954336,"gc":[755,504,504],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20080,"sharedPasses":5020,"driverPasses":5020,"browserPasses":5020}
|
||||
{"cycle":2520,"elapsedSeconds":3354.5560829,"utc":"2026-11-10T18:40:39.6811693Z","WorkingSet64":135950336,"PrivateMemorySize64":248168448,"managedBytes":4631704,"allocatedBytes":11794779224,"gc":[758,506,506],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20160,"sharedPasses":5040,"driverPasses":5040,"browserPasses":5040}
|
||||
{"cycle":2530,"elapsedSeconds":3367.8831981,"utc":"2026-11-10T18:40:53.0005831Z","WorkingSet64":135389184,"PrivateMemorySize64":248168448,"managedBytes":4647712,"allocatedBytes":11841513312,"gc":[761,508,508],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20240,"sharedPasses":5060,"driverPasses":5060,"browserPasses":5060}
|
||||
{"cycle":2540,"elapsedSeconds":3381.0004846,"utc":"2026-11-10T18:41:06.1205752Z","WorkingSet64":135471104,"PrivateMemorySize64":248168448,"managedBytes":4638504,"allocatedBytes":11888204224,"gc":[764,510,510],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20320,"sharedPasses":5080,"driverPasses":5080,"browserPasses":5080}
|
||||
{"cycle":2550,"elapsedSeconds":3394.3315319,"utc":"2026-11-10T18:41:19.4601963Z","WorkingSet64":136192000,"PrivateMemorySize64":248168448,"managedBytes":4522104,"allocatedBytes":11934927096,"gc":[767,512,512],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20400,"sharedPasses":5100,"driverPasses":5100,"browserPasses":5100}
|
||||
{"cycle":2560,"elapsedSeconds":3407.6387038,"utc":"2026-11-10T18:41:32.7662565Z","WorkingSet64":135135232,"PrivateMemorySize64":248299520,"managedBytes":4630568,"allocatedBytes":11981734184,"gc":[770,514,514],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20480,"sharedPasses":5120,"driverPasses":5120,"browserPasses":5120}
|
||||
{"cycle":2570,"elapsedSeconds":3420.9414793,"utc":"2026-11-10T18:41:46.0672593Z","WorkingSet64":134914048,"PrivateMemorySize64":248000512,"managedBytes":4516672,"allocatedBytes":12028474912,"gc":[773,516,516],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20560,"sharedPasses":5140,"driverPasses":5140,"browserPasses":5140}
|
||||
{"cycle":2580,"elapsedSeconds":3434.1467509,"utc":"2026-11-10T18:41:59.2686931Z","WorkingSet64":134914048,"PrivateMemorySize64":248000512,"managedBytes":4517360,"allocatedBytes":12075178416,"gc":[776,518,518],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20640,"sharedPasses":5160,"driverPasses":5160,"browserPasses":5160}
|
||||
{"cycle":2590,"elapsedSeconds":3447.4953282,"utc":"2026-11-10T18:42:12.6155439Z","WorkingSet64":134914048,"PrivateMemorySize64":248000512,"managedBytes":4516840,"allocatedBytes":12121868976,"gc":[779,520,520],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20720,"sharedPasses":5180,"driverPasses":5180,"browserPasses":5180}
|
||||
{"cycle":2600,"elapsedSeconds":3460.8180704,"utc":"2026-11-10T18:42:25.9432168Z","WorkingSet64":134602752,"PrivateMemorySize64":248020992,"managedBytes":4565960,"allocatedBytes":12168611952,"gc":[782,522,522],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20800,"sharedPasses":5200,"driverPasses":5200,"browserPasses":5200}
|
||||
{"cycle":2610,"elapsedSeconds":3474.1409163,"utc":"2026-11-10T18:42:39.2626345Z","WorkingSet64":134602752,"PrivateMemorySize64":248000512,"managedBytes":4500424,"allocatedBytes":12215376536,"gc":[785,524,524],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20880,"sharedPasses":5220,"driverPasses":5220,"browserPasses":5220}
|
||||
{"cycle":2620,"elapsedSeconds":3487.4384872,"utc":"2026-11-10T18:42:52.5635596Z","WorkingSet64":134602752,"PrivateMemorySize64":248020992,"managedBytes":4520640,"allocatedBytes":12262106888,"gc":[788,526,526],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":20960,"sharedPasses":5240,"driverPasses":5240,"browserPasses":5240}
|
||||
{"cycle":2630,"elapsedSeconds":3500.7409119,"utc":"2026-11-10T18:43:05.8637513Z","WorkingSet64":134189056,"PrivateMemorySize64":248086528,"managedBytes":4630392,"allocatedBytes":12308912040,"gc":[791,528,528],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21040,"sharedPasses":5260,"driverPasses":5260,"browserPasses":5260}
|
||||
{"cycle":2640,"elapsedSeconds":3514.0138351,"utc":"2026-11-10T18:43:19.1419709Z","WorkingSet64":139644928,"PrivateMemorySize64":248152064,"managedBytes":4647896,"allocatedBytes":12355632440,"gc":[794,530,530],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21120,"sharedPasses":5280,"driverPasses":5280,"browserPasses":5280}
|
||||
{"cycle":2650,"elapsedSeconds":3526.8578798,"utc":"2026-11-10T18:43:31.9756614Z","WorkingSet64":139644928,"PrivateMemorySize64":248131584,"managedBytes":4517072,"allocatedBytes":12402336256,"gc":[797,532,532],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21200,"sharedPasses":5300,"driverPasses":5300,"browserPasses":5300}
|
||||
{"cycle":2660,"elapsedSeconds":3540.056546,"utc":"2026-11-10T18:43:45.1735061Z","WorkingSet64":139644928,"PrivateMemorySize64":248152064,"managedBytes":4542416,"allocatedBytes":12449079888,"gc":[800,534,534],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21280,"sharedPasses":5320,"driverPasses":5320,"browserPasses":5320}
|
||||
{"cycle":2670,"elapsedSeconds":3553.2562429,"utc":"2026-11-10T18:43:58.3748788Z","WorkingSet64":139644928,"PrivateMemorySize64":248152064,"managedBytes":4613040,"allocatedBytes":12495855928,"gc":[803,536,536],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21360,"sharedPasses":5340,"driverPasses":5340,"browserPasses":5340}
|
||||
{"cycle":2680,"elapsedSeconds":3566.5138326,"utc":"2026-11-10T18:44:11.6413995Z","WorkingSet64":139644928,"PrivateMemorySize64":248152064,"managedBytes":4631928,"allocatedBytes":12542572184,"gc":[806,538,538],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21440,"sharedPasses":5360,"driverPasses":5360,"browserPasses":5360}
|
||||
{"cycle":2690,"elapsedSeconds":3579.6225905,"utc":"2026-11-10T18:44:24.7434194Z","WorkingSet64":139644928,"PrivateMemorySize64":248152064,"managedBytes":4631168,"allocatedBytes":12589270856,"gc":[809,540,540],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21520,"sharedPasses":5380,"driverPasses":5380,"browserPasses":5380}
|
||||
{"cycle":2700,"elapsedSeconds":3592.7408581,"utc":"2026-11-10T18:44:37.8674278Z","WorkingSet64":139956224,"PrivateMemorySize64":248152064,"managedBytes":4647680,"allocatedBytes":12636014544,"gc":[812,542,542],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21600,"sharedPasses":5400,"driverPasses":5400,"browserPasses":5400}
|
||||
{"cycle":2710,"elapsedSeconds":3605.9803556,"utc":"2026-11-10T18:44:51.1101771Z","WorkingSet64":141332480,"PrivateMemorySize64":248152064,"managedBytes":4647384,"allocatedBytes":12683677808,"gc":[815,544,544],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21680,"sharedPasses":5420,"driverPasses":5420,"browserPasses":5420}
|
||||
{"cycle":2720,"elapsedSeconds":3619.223102,"utc":"2026-11-10T18:45:04.348735Z","WorkingSet64":141332480,"PrivateMemorySize64":248131584,"managedBytes":4532640,"allocatedBytes":12730386976,"gc":[818,546,546],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21760,"sharedPasses":5440,"driverPasses":5440,"browserPasses":5440}
|
||||
{"cycle":2730,"elapsedSeconds":3632.4494909,"utc":"2026-11-10T18:45:17.5780367Z","WorkingSet64":141062144,"PrivateMemorySize64":248152064,"managedBytes":4580712,"allocatedBytes":12777158240,"gc":[821,548,548],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21840,"sharedPasses":5460,"driverPasses":5460,"browserPasses":5460}
|
||||
{"cycle":2740,"elapsedSeconds":3645.6272895,"utc":"2026-11-10T18:45:30.7554742Z","WorkingSet64":141156352,"PrivateMemorySize64":248152064,"managedBytes":4646272,"allocatedBytes":12823938024,"gc":[824,550,550],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":21920,"sharedPasses":5480,"driverPasses":5480,"browserPasses":5480}
|
||||
{"cycle":2750,"elapsedSeconds":3658.8946812,"utc":"2026-11-10T18:45:44.0174653Z","WorkingSet64":141156352,"PrivateMemorySize64":248152064,"managedBytes":4647376,"allocatedBytes":12870643728,"gc":[827,552,552],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22000,"sharedPasses":5500,"driverPasses":5500,"browserPasses":5500}
|
||||
{"cycle":2760,"elapsedSeconds":3672.0557723,"utc":"2026-11-10T18:45:57.174906Z","WorkingSet64":141156352,"PrivateMemorySize64":248131584,"managedBytes":4517248,"allocatedBytes":12917347840,"gc":[830,554,554],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22080,"sharedPasses":5520,"driverPasses":5520,"browserPasses":5520}
|
||||
{"cycle":2770,"elapsedSeconds":3685.3576271,"utc":"2026-11-10T18:46:10.4785831Z","WorkingSet64":140980224,"PrivateMemorySize64":248152064,"managedBytes":4579992,"allocatedBytes":12964116272,"gc":[833,556,556],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22160,"sharedPasses":5540,"driverPasses":5540,"browserPasses":5540}
|
||||
{"cycle":2780,"elapsedSeconds":3698.5960382,"utc":"2026-11-10T18:46:23.7235744Z","WorkingSet64":141484032,"PrivateMemorySize64":248131584,"managedBytes":4517024,"allocatedBytes":13010832224,"gc":[836,558,558],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22240,"sharedPasses":5560,"driverPasses":5560,"browserPasses":5560}
|
||||
{"cycle":2790,"elapsedSeconds":3711.8593586,"utc":"2026-11-10T18:46:36.9839413Z","WorkingSet64":141484032,"PrivateMemorySize64":248152064,"managedBytes":4581680,"allocatedBytes":13057584568,"gc":[839,560,560],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22320,"sharedPasses":5580,"driverPasses":5580,"browserPasses":5580}
|
||||
{"cycle":2800,"elapsedSeconds":3725.1404624,"utc":"2026-11-10T18:46:50.2673849Z","WorkingSet64":140398592,"PrivateMemorySize64":248152064,"managedBytes":4566080,"allocatedBytes":13104297184,"gc":[842,562,562],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22400,"sharedPasses":5600,"driverPasses":5600,"browserPasses":5600}
|
||||
{"cycle":2810,"elapsedSeconds":3738.4281808,"utc":"2026-11-10T18:47:03.5492228Z","WorkingSet64":140398592,"PrivateMemorySize64":248152064,"managedBytes":4631072,"allocatedBytes":13151092496,"gc":[845,564,564],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22480,"sharedPasses":5620,"driverPasses":5620,"browserPasses":5620}
|
||||
{"cycle":2820,"elapsedSeconds":3751.7036567,"utc":"2026-11-10T18:47:16.8320698Z","WorkingSet64":140398592,"PrivateMemorySize64":248152064,"managedBytes":4646096,"allocatedBytes":13197811040,"gc":[848,566,566],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22560,"sharedPasses":5640,"driverPasses":5640,"browserPasses":5640}
|
||||
{"cycle":2830,"elapsedSeconds":3764.8288594,"utc":"2026-11-10T18:47:29.9490464Z","WorkingSet64":140398592,"PrivateMemorySize64":248152064,"managedBytes":4647088,"allocatedBytes":13244521016,"gc":[851,568,568],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22640,"sharedPasses":5660,"driverPasses":5660,"browserPasses":5660}
|
||||
{"cycle":2840,"elapsedSeconds":3778.0234287,"utc":"2026-11-10T18:47:43.1525105Z","WorkingSet64":140144640,"PrivateMemorySize64":248152064,"managedBytes":4587488,"allocatedBytes":13291310552,"gc":[854,570,570],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22720,"sharedPasses":5680,"driverPasses":5680,"browserPasses":5680}
|
||||
{"cycle":2850,"elapsedSeconds":3791.1815004,"utc":"2026-11-10T18:47:56.310184Z","WorkingSet64":140185600,"PrivateMemorySize64":248152064,"managedBytes":4630160,"allocatedBytes":13338052256,"gc":[857,572,572],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22800,"sharedPasses":5700,"driverPasses":5700,"browserPasses":5700}
|
||||
{"cycle":2860,"elapsedSeconds":3804.3095771,"utc":"2026-11-10T18:48:09.4272408Z","WorkingSet64":140505088,"PrivateMemorySize64":248131584,"managedBytes":4501000,"allocatedBytes":13384764736,"gc":[860,574,574],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22880,"sharedPasses":5720,"driverPasses":5720,"browserPasses":5720}
|
||||
{"cycle":2870,"elapsedSeconds":3817.6499627,"utc":"2026-11-10T18:48:22.7774667Z","WorkingSet64":136892416,"PrivateMemorySize64":248152064,"managedBytes":4549000,"allocatedBytes":13431517264,"gc":[863,576,576],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":22960,"sharedPasses":5740,"driverPasses":5740,"browserPasses":5740}
|
||||
{"cycle":2880,"elapsedSeconds":3830.737646,"utc":"2026-11-10T18:48:35.8674593Z","WorkingSet64":136892416,"PrivateMemorySize64":248152064,"managedBytes":4630744,"allocatedBytes":13478305280,"gc":[866,578,578],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23040,"sharedPasses":5760,"driverPasses":5760,"browserPasses":5760}
|
||||
{"cycle":2890,"elapsedSeconds":3843.9766521,"utc":"2026-11-10T18:48:49.0941582Z","WorkingSet64":136892416,"PrivateMemorySize64":248152064,"managedBytes":4622360,"allocatedBytes":13524996168,"gc":[869,580,580],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23120,"sharedPasses":5780,"driverPasses":5780,"browserPasses":5780}
|
||||
{"cycle":2900,"elapsedSeconds":3857.2735939,"utc":"2026-11-10T18:49:02.3907588Z","WorkingSet64":136867840,"PrivateMemorySize64":248152064,"managedBytes":4630744,"allocatedBytes":13571712840,"gc":[872,582,582],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23200,"sharedPasses":5800,"driverPasses":5800,"browserPasses":5800}
|
||||
{"cycle":2910,"elapsedSeconds":3870.5382781,"utc":"2026-11-10T18:49:15.6655812Z","WorkingSet64":136867840,"PrivateMemorySize64":248131584,"managedBytes":4581584,"allocatedBytes":13618420552,"gc":[875,584,584],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23280,"sharedPasses":5820,"driverPasses":5820,"browserPasses":5820}
|
||||
{"cycle":2920,"elapsedSeconds":3883.7917365,"utc":"2026-11-10T18:49:28.9257285Z","WorkingSet64":136867840,"PrivateMemorySize64":248152064,"managedBytes":4627880,"allocatedBytes":13665165368,"gc":[878,586,586],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23360,"sharedPasses":5840,"driverPasses":5840,"browserPasses":5840}
|
||||
{"cycle":2930,"elapsedSeconds":3896.8911756,"utc":"2026-11-10T18:49:42.0086581Z","WorkingSet64":136867840,"PrivateMemorySize64":248152064,"managedBytes":4647864,"allocatedBytes":13711888832,"gc":[881,588,588],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23440,"sharedPasses":5860,"driverPasses":5860,"browserPasses":5860}
|
||||
{"cycle":2940,"elapsedSeconds":3910.2108164,"utc":"2026-11-10T18:49:55.3286969Z","WorkingSet64":139603968,"PrivateMemorySize64":248152064,"managedBytes":4646288,"allocatedBytes":13759572072,"gc":[884,590,590],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23520,"sharedPasses":5880,"driverPasses":5880,"browserPasses":5880}
|
||||
{"cycle":2950,"elapsedSeconds":3923.5292088,"utc":"2026-11-10T18:50:08.654244Z","WorkingSet64":139603968,"PrivateMemorySize64":248152064,"managedBytes":4565440,"allocatedBytes":13806315856,"gc":[887,592,592],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23600,"sharedPasses":5900,"driverPasses":5900,"browserPasses":5900}
|
||||
{"cycle":2960,"elapsedSeconds":3936.7270001,"utc":"2026-11-10T18:50:21.8539265Z","WorkingSet64":139603968,"PrivateMemorySize64":248152064,"managedBytes":4582136,"allocatedBytes":13853038400,"gc":[890,594,594],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23680,"sharedPasses":5920,"driverPasses":5920,"browserPasses":5920}
|
||||
{"cycle":2970,"elapsedSeconds":3950.0404741,"utc":"2026-11-10T18:50:35.1657556Z","WorkingSet64":139108352,"PrivateMemorySize64":248131584,"managedBytes":4517256,"allocatedBytes":13899751392,"gc":[893,596,596],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23760,"sharedPasses":5940,"driverPasses":5940,"browserPasses":5940}
|
||||
{"cycle":2980,"elapsedSeconds":3963.3270102,"utc":"2026-11-10T18:50:48.4527189Z","WorkingSet64":139214848,"PrivateMemorySize64":248131584,"managedBytes":4517168,"allocatedBytes":13946457296,"gc":[896,598,598],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23840,"sharedPasses":5960,"driverPasses":5960,"browserPasses":5960}
|
||||
{"cycle":2990,"elapsedSeconds":3976.5313651,"utc":"2026-11-10T18:51:01.6571171Z","WorkingSet64":139214848,"PrivateMemorySize64":248131584,"managedBytes":4517592,"allocatedBytes":13993163408,"gc":[899,600,600],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":23920,"sharedPasses":5980,"driverPasses":5980,"browserPasses":5980}
|
||||
{"cycle":3000,"elapsedSeconds":3989.775694,"utc":"2026-11-10T18:51:14.8931471Z","WorkingSet64":139214848,"PrivateMemorySize64":248131584,"managedBytes":4517128,"allocatedBytes":14039860608,"gc":[902,602,602],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24000,"sharedPasses":6000,"driverPasses":6000,"browserPasses":6000}
|
||||
{"cycle":3010,"elapsedSeconds":4003.0564251,"utc":"2026-11-10T18:51:28.1747748Z","WorkingSet64":138244096,"PrivateMemorySize64":248152064,"managedBytes":4648040,"allocatedBytes":14086691072,"gc":[905,604,604],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24080,"sharedPasses":6020,"driverPasses":6020,"browserPasses":6020}
|
||||
{"cycle":3020,"elapsedSeconds":4016.3596689,"utc":"2026-11-10T18:51:41.4865308Z","WorkingSet64":138244096,"PrivateMemorySize64":248152064,"managedBytes":4632616,"allocatedBytes":14133515816,"gc":[908,606,606],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24160,"sharedPasses":6040,"driverPasses":6040,"browserPasses":6040}
|
||||
{"cycle":3030,"elapsedSeconds":4029.4609105,"utc":"2026-11-10T18:51:54.5782268Z","WorkingSet64":138244096,"PrivateMemorySize64":248152064,"managedBytes":4646904,"allocatedBytes":14180220760,"gc":[911,608,608],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24240,"sharedPasses":6060,"driverPasses":6060,"browserPasses":6060}
|
||||
{"cycle":3040,"elapsedSeconds":4042.781307,"utc":"2026-11-10T18:52:07.9075421Z","WorkingSet64":137908224,"PrivateMemorySize64":248152064,"managedBytes":4522720,"allocatedBytes":14226926368,"gc":[914,610,610],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24320,"sharedPasses":6080,"driverPasses":6080,"browserPasses":6080}
|
||||
{"cycle":3050,"elapsedSeconds":4055.9007532,"utc":"2026-11-10T18:52:21.0227135Z","WorkingSet64":137908224,"PrivateMemorySize64":248152064,"managedBytes":4521968,"allocatedBytes":14273626640,"gc":[917,612,612],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24400,"sharedPasses":6100,"driverPasses":6100,"browserPasses":6100}
|
||||
{"cycle":3060,"elapsedSeconds":4069.1601534,"utc":"2026-11-10T18:52:34.2860243Z","WorkingSet64":137908224,"PrivateMemorySize64":248131584,"managedBytes":4517240,"allocatedBytes":14320336456,"gc":[920,614,614],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24480,"sharedPasses":6120,"driverPasses":6120,"browserPasses":6120}
|
||||
{"cycle":3070,"elapsedSeconds":4082.4767702,"utc":"2026-11-10T18:52:47.6078749Z","WorkingSet64":135692288,"PrivateMemorySize64":248152064,"managedBytes":4518712,"allocatedBytes":14367054848,"gc":[923,616,616],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24560,"sharedPasses":6140,"driverPasses":6140,"browserPasses":6140}
|
||||
{"cycle":3080,"elapsedSeconds":4095.6692935,"utc":"2026-11-10T18:53:00.786607Z","WorkingSet64":135794688,"PrivateMemorySize64":248238080,"managedBytes":4671568,"allocatedBytes":14413927928,"gc":[926,618,618],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24640,"sharedPasses":6160,"driverPasses":6160,"browserPasses":6160}
|
||||
{"cycle":3090,"elapsedSeconds":4108.7808298,"utc":"2026-11-10T18:53:13.8980819Z","WorkingSet64":138858496,"PrivateMemorySize64":248217600,"managedBytes":4623072,"allocatedBytes":14460655128,"gc":[929,620,620],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24720,"sharedPasses":6180,"driverPasses":6180,"browserPasses":6180}
|
||||
{"cycle":3100,"elapsedSeconds":4121.8051343,"utc":"2026-11-10T18:53:26.9329517Z","WorkingSet64":138858496,"PrivateMemorySize64":248217600,"managedBytes":4521688,"allocatedBytes":14507368056,"gc":[932,622,622],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24800,"sharedPasses":6200,"driverPasses":6200,"browserPasses":6200}
|
||||
{"cycle":3110,"elapsedSeconds":4135.0963146,"utc":"2026-11-10T18:53:40.2235589Z","WorkingSet64":138846208,"PrivateMemorySize64":248217600,"managedBytes":4522096,"allocatedBytes":14554070984,"gc":[935,624,624],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24880,"sharedPasses":6220,"driverPasses":6220,"browserPasses":6220}
|
||||
{"cycle":3120,"elapsedSeconds":4148.3809262,"utc":"2026-11-10T18:53:53.5079928Z","WorkingSet64":138846208,"PrivateMemorySize64":248197120,"managedBytes":4517784,"allocatedBytes":14600769808,"gc":[938,626,626],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":24960,"sharedPasses":6240,"driverPasses":6240,"browserPasses":6240}
|
||||
{"cycle":3130,"elapsedSeconds":4161.6205539,"utc":"2026-11-10T18:54:06.7503381Z","WorkingSet64":138846208,"PrivateMemorySize64":248217600,"managedBytes":4581512,"allocatedBytes":14647535656,"gc":[941,628,628],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25040,"sharedPasses":6260,"driverPasses":6260,"browserPasses":6260}
|
||||
{"cycle":3140,"elapsedSeconds":4174.8286306,"utc":"2026-11-10T18:54:19.9581221Z","WorkingSet64":138493952,"PrivateMemorySize64":248217600,"managedBytes":4647448,"allocatedBytes":14694314880,"gc":[944,630,630],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25120,"sharedPasses":6280,"driverPasses":6280,"browserPasses":6280}
|
||||
{"cycle":3150,"elapsedSeconds":4187.9317212,"utc":"2026-11-10T18:54:33.0591689Z","WorkingSet64":138493952,"PrivateMemorySize64":248217600,"managedBytes":4647760,"allocatedBytes":14741025784,"gc":[947,632,632],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25200,"sharedPasses":6300,"driverPasses":6300,"browserPasses":6300}
|
||||
{"cycle":3160,"elapsedSeconds":4201.3385167,"utc":"2026-11-10T18:54:46.466935Z","WorkingSet64":138625024,"PrivateMemorySize64":248217600,"managedBytes":4543056,"allocatedBytes":14787734648,"gc":[950,634,634],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25280,"sharedPasses":6320,"driverPasses":6320,"browserPasses":6320}
|
||||
{"cycle":3170,"elapsedSeconds":4214.6318822,"utc":"2026-11-10T18:54:59.7643932Z","WorkingSet64":139108352,"PrivateMemorySize64":248238080,"managedBytes":4598704,"allocatedBytes":14835471712,"gc":[953,636,636],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25360,"sharedPasses":6340,"driverPasses":6340,"browserPasses":6340}
|
||||
{"cycle":3180,"elapsedSeconds":4227.6011572,"utc":"2026-11-10T18:55:12.7217844Z","WorkingSet64":138567680,"PrivateMemorySize64":248258560,"managedBytes":4599088,"allocatedBytes":14882179040,"gc":[956,638,638],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25440,"sharedPasses":6360,"driverPasses":6360,"browserPasses":6360}
|
||||
{"cycle":3190,"elapsedSeconds":4240.8800341,"utc":"2026-11-10T18:55:26.0053482Z","WorkingSet64":138567680,"PrivateMemorySize64":248197120,"managedBytes":4521984,"allocatedBytes":14928870384,"gc":[959,640,640],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25520,"sharedPasses":6380,"driverPasses":6380,"browserPasses":6380}
|
||||
{"cycle":3200,"elapsedSeconds":4254.0874218,"utc":"2026-11-10T18:55:39.2142131Z","WorkingSet64":138567680,"PrivateMemorySize64":248197120,"managedBytes":4522008,"allocatedBytes":14975574208,"gc":[962,642,642],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25600,"sharedPasses":6400,"driverPasses":6400,"browserPasses":6400}
|
||||
{"cycle":3210,"elapsedSeconds":4267.3777322,"utc":"2026-11-10T18:55:52.503358Z","WorkingSet64":138256384,"PrivateMemorySize64":248197120,"managedBytes":4521768,"allocatedBytes":15022280560,"gc":[965,644,644],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25680,"sharedPasses":6420,"driverPasses":6420,"browserPasses":6420}
|
||||
{"cycle":3220,"elapsedSeconds":4280.6564608,"utc":"2026-11-10T18:56:05.7824027Z","WorkingSet64":138256384,"PrivateMemorySize64":248197120,"managedBytes":4522432,"allocatedBytes":15068975584,"gc":[968,646,646],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25760,"sharedPasses":6440,"driverPasses":6440,"browserPasses":6440}
|
||||
{"cycle":3230,"elapsedSeconds":4293.8763882,"utc":"2026-11-10T18:56:19.0056502Z","WorkingSet64":138256384,"PrivateMemorySize64":248197120,"managedBytes":4521064,"allocatedBytes":15115690104,"gc":[971,648,648],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25840,"sharedPasses":6460,"driverPasses":6460,"browserPasses":6460}
|
||||
{"cycle":3240,"elapsedSeconds":4307.0704815,"utc":"2026-11-10T18:56:32.2035835Z","WorkingSet64":136998912,"PrivateMemorySize64":248197120,"managedBytes":4522648,"allocatedBytes":15162383368,"gc":[974,650,650],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":25920,"sharedPasses":6480,"driverPasses":6480,"browserPasses":6480}
|
||||
{"cycle":3250,"elapsedSeconds":4320.2882786,"utc":"2026-11-10T18:56:45.4147471Z","WorkingSet64":136998912,"PrivateMemorySize64":248217600,"managedBytes":4635296,"allocatedBytes":15209206344,"gc":[977,652,652],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26000,"sharedPasses":6500,"driverPasses":6500,"browserPasses":6500}
|
||||
{"cycle":3260,"elapsedSeconds":4333.5584568,"utc":"2026-11-10T18:56:58.6781374Z","WorkingSet64":136998912,"PrivateMemorySize64":248217600,"managedBytes":4568600,"allocatedBytes":15255964944,"gc":[980,654,654],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26080,"sharedPasses":6520,"driverPasses":6520,"browserPasses":6520}
|
||||
{"cycle":3270,"elapsedSeconds":4347.0606786,"utc":"2026-11-10T18:57:12.1841117Z","WorkingSet64":137113600,"PrivateMemorySize64":248303616,"managedBytes":4791072,"allocatedBytes":15302893912,"gc":[983,656,656],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26160,"sharedPasses":6540,"driverPasses":6540,"browserPasses":6540}
|
||||
{"cycle":3280,"elapsedSeconds":4360.31061,"utc":"2026-11-10T18:57:25.4340341Z","WorkingSet64":137121792,"PrivateMemorySize64":248283136,"managedBytes":4651432,"allocatedBytes":15349591520,"gc":[986,658,658],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26240,"sharedPasses":6560,"driverPasses":6560,"browserPasses":6560}
|
||||
{"cycle":3290,"elapsedSeconds":4373.5743455,"utc":"2026-11-10T18:57:38.6952524Z","WorkingSet64":137121792,"PrivateMemorySize64":248283136,"managedBytes":4635624,"allocatedBytes":15396295048,"gc":[989,660,660],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26320,"sharedPasses":6580,"driverPasses":6580,"browserPasses":6580}
|
||||
{"cycle":3300,"elapsedSeconds":4386.6887803,"utc":"2026-11-10T18:57:51.8081916Z","WorkingSet64":137121792,"PrivateMemorySize64":248283136,"managedBytes":4586872,"allocatedBytes":15443079392,"gc":[992,662,662],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26400,"sharedPasses":6600,"driverPasses":6600,"browserPasses":6600}
|
||||
{"cycle":3310,"elapsedSeconds":4399.9113254,"utc":"2026-11-10T18:58:05.0420444Z","WorkingSet64":136998912,"PrivateMemorySize64":248283136,"managedBytes":4567968,"allocatedBytes":15489781728,"gc":[995,664,664],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26480,"sharedPasses":6620,"driverPasses":6620,"browserPasses":6620}
|
||||
{"cycle":3320,"elapsedSeconds":4413.0580019,"utc":"2026-11-10T18:58:18.1870197Z","WorkingSet64":136998912,"PrivateMemorySize64":248283136,"managedBytes":4592464,"allocatedBytes":15536553896,"gc":[998,666,666],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26560,"sharedPasses":6640,"driverPasses":6640,"browserPasses":6640}
|
||||
{"cycle":3330,"elapsedSeconds":4426.2459223,"utc":"2026-11-10T18:58:31.3722185Z","WorkingSet64":136998912,"PrivateMemorySize64":248283136,"managedBytes":4635720,"allocatedBytes":15583333064,"gc":[1001,668,668],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26640,"sharedPasses":6660,"driverPasses":6660,"browserPasses":6660}
|
||||
{"cycle":3340,"elapsedSeconds":4439.4945903,"utc":"2026-11-10T18:58:44.612778Z","WorkingSet64":136998912,"PrivateMemorySize64":248262656,"managedBytes":4512544,"allocatedBytes":15630045576,"gc":[1004,670,670],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26720,"sharedPasses":6680,"driverPasses":6680,"browserPasses":6680}
|
||||
{"cycle":3350,"elapsedSeconds":4452.7319327,"utc":"2026-11-10T18:58:57.8504798Z","WorkingSet64":136871936,"PrivateMemorySize64":248262656,"managedBytes":4513304,"allocatedBytes":15676735472,"gc":[1007,672,672],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26800,"sharedPasses":6700,"driverPasses":6700,"browserPasses":6700}
|
||||
{"cycle":3360,"elapsedSeconds":4465.9665357,"utc":"2026-11-10T18:59:11.0915659Z","WorkingSet64":136871936,"PrivateMemorySize64":248262656,"managedBytes":4522208,"allocatedBytes":15723446584,"gc":[1010,674,674],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26880,"sharedPasses":6720,"driverPasses":6720,"browserPasses":6720}
|
||||
{"cycle":3370,"elapsedSeconds":4479.2453575,"utc":"2026-11-10T18:59:24.3656984Z","WorkingSet64":136871936,"PrivateMemorySize64":248262656,"managedBytes":4521360,"allocatedBytes":15770144424,"gc":[1013,676,676],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":26960,"sharedPasses":6740,"driverPasses":6740,"browserPasses":6740}
|
||||
{"cycle":3380,"elapsedSeconds":4492.5037895,"utc":"2026-11-10T18:59:37.6220691Z","WorkingSet64":136712192,"PrivateMemorySize64":248283136,"managedBytes":4620792,"allocatedBytes":15816956776,"gc":[1016,678,678],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27040,"sharedPasses":6760,"driverPasses":6760,"browserPasses":6760}
|
||||
{"cycle":3390,"elapsedSeconds":4505.7328701,"utc":"2026-11-10T18:59:50.8520389Z","WorkingSet64":139632640,"PrivateMemorySize64":248283136,"managedBytes":4521248,"allocatedBytes":15864653768,"gc":[1019,680,680],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27120,"sharedPasses":6780,"driverPasses":6780,"browserPasses":6780}
|
||||
{"cycle":3400,"elapsedSeconds":4518.9633225,"utc":"2026-11-10T19:00:04.0810038Z","WorkingSet64":139632640,"PrivateMemorySize64":248262656,"managedBytes":4521944,"allocatedBytes":15911375032,"gc":[1022,682,682],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27200,"sharedPasses":6800,"driverPasses":6800,"browserPasses":6800}
|
||||
{"cycle":3410,"elapsedSeconds":4532.2249832,"utc":"2026-11-10T19:00:17.3425888Z","WorkingSet64":138752000,"PrivateMemorySize64":248262656,"managedBytes":4521312,"allocatedBytes":15958071720,"gc":[1025,684,684],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27280,"sharedPasses":6820,"driverPasses":6820,"browserPasses":6820}
|
||||
{"cycle":3420,"elapsedSeconds":4545.4773934,"utc":"2026-11-10T19:00:30.5988211Z","WorkingSet64":138752000,"PrivateMemorySize64":248262656,"managedBytes":4521496,"allocatedBytes":16004773048,"gc":[1028,686,686],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27360,"sharedPasses":6840,"driverPasses":6840,"browserPasses":6840}
|
||||
{"cycle":3430,"elapsedSeconds":4558.6764164,"utc":"2026-11-10T19:00:43.7997598Z","WorkingSet64":138752000,"PrivateMemorySize64":248262656,"managedBytes":4521744,"allocatedBytes":16051486320,"gc":[1031,688,688],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27440,"sharedPasses":6860,"driverPasses":6860,"browserPasses":6860}
|
||||
{"cycle":3440,"elapsedSeconds":4571.9136606,"utc":"2026-11-10T19:00:57.0388739Z","WorkingSet64":138752000,"PrivateMemorySize64":248283136,"managedBytes":4652224,"allocatedBytes":16098326496,"gc":[1034,690,690],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27520,"sharedPasses":6880,"driverPasses":6880,"browserPasses":6880}
|
||||
{"cycle":3450,"elapsedSeconds":4585.1241096,"utc":"2026-11-10T19:01:10.2418696Z","WorkingSet64":137261056,"PrivateMemorySize64":248283136,"managedBytes":4550992,"allocatedBytes":16145065184,"gc":[1037,692,692],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27600,"sharedPasses":6900,"driverPasses":6900,"browserPasses":6900}
|
||||
{"cycle":3460,"elapsedSeconds":4598.3889279,"utc":"2026-11-10T19:01:23.5146186Z","WorkingSet64":137261056,"PrivateMemorySize64":248283136,"managedBytes":4650856,"allocatedBytes":16191862272,"gc":[1040,694,694],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27680,"sharedPasses":6920,"driverPasses":6920,"browserPasses":6920}
|
||||
{"cycle":3470,"elapsedSeconds":4611.6232963,"utc":"2026-11-10T19:01:36.7478109Z","WorkingSet64":139436032,"PrivateMemorySize64":248283136,"managedBytes":4652152,"allocatedBytes":16238573160,"gc":[1043,696,696],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27760,"sharedPasses":6940,"driverPasses":6940,"browserPasses":6940}
|
||||
{"cycle":3480,"elapsedSeconds":4624.8695604,"utc":"2026-11-10T19:01:49.9939805Z","WorkingSet64":139436032,"PrivateMemorySize64":248283136,"managedBytes":4652288,"allocatedBytes":16285267016,"gc":[1046,698,698],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27840,"sharedPasses":6960,"driverPasses":6960,"browserPasses":6960}
|
||||
{"cycle":3490,"elapsedSeconds":4638.140508,"utc":"2026-11-10T19:02:03.25852Z","WorkingSet64":139436032,"PrivateMemorySize64":248283136,"managedBytes":4618680,"allocatedBytes":16332074272,"gc":[1049,700,700],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":27920,"sharedPasses":6980,"driverPasses":6980,"browserPasses":6980}
|
||||
{"cycle":3500,"elapsedSeconds":4651.3904809,"utc":"2026-11-10T19:02:16.5174099Z","WorkingSet64":139436032,"PrivateMemorySize64":248303616,"managedBytes":4773480,"allocatedBytes":16378936696,"gc":[1052,702,702],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28000,"sharedPasses":7000,"driverPasses":7000,"browserPasses":7000}
|
||||
{"cycle":3510,"elapsedSeconds":4664.5917749,"utc":"2026-11-10T19:02:29.7095169Z","WorkingSet64":139436032,"PrivateMemorySize64":248303616,"managedBytes":4765560,"allocatedBytes":16425639952,"gc":[1055,704,704],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28080,"sharedPasses":7020,"driverPasses":7020,"browserPasses":7020}
|
||||
{"cycle":3520,"elapsedSeconds":4677.7814582,"utc":"2026-11-10T19:02:42.908182Z","WorkingSet64":139292672,"PrivateMemorySize64":248303616,"managedBytes":4724608,"allocatedBytes":16472430776,"gc":[1058,706,706],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28160,"sharedPasses":7040,"driverPasses":7040,"browserPasses":7040}
|
||||
{"cycle":3530,"elapsedSeconds":4691.0688619,"utc":"2026-11-10T19:02:56.190364Z","WorkingSet64":139292672,"PrivateMemorySize64":248303616,"managedBytes":4691408,"allocatedBytes":16519131792,"gc":[1061,708,708],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28240,"sharedPasses":7060,"driverPasses":7060,"browserPasses":7060}
|
||||
{"cycle":3540,"elapsedSeconds":4704.2841341,"utc":"2026-11-10T19:03:09.4022211Z","WorkingSet64":139292672,"PrivateMemorySize64":248303616,"managedBytes":4647248,"allocatedBytes":16565886696,"gc":[1064,710,710],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28320,"sharedPasses":7080,"driverPasses":7080,"browserPasses":7080}
|
||||
{"cycle":3550,"elapsedSeconds":4717.5353571,"utc":"2026-11-10T19:03:22.6560999Z","WorkingSet64":138264576,"PrivateMemorySize64":248303616,"managedBytes":4665064,"allocatedBytes":16612615656,"gc":[1067,712,712],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28400,"sharedPasses":7100,"driverPasses":7100,"browserPasses":7100}
|
||||
{"cycle":3560,"elapsedSeconds":4730.7733147,"utc":"2026-11-10T19:03:35.8979401Z","WorkingSet64":138264576,"PrivateMemorySize64":248283136,"managedBytes":4635016,"allocatedBytes":16659417976,"gc":[1070,714,714],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28480,"sharedPasses":7120,"driverPasses":7120,"browserPasses":7120}
|
||||
{"cycle":3570,"elapsedSeconds":4744.0214695,"utc":"2026-11-10T19:03:49.1402769Z","WorkingSet64":138264576,"PrivateMemorySize64":248303616,"managedBytes":4773816,"allocatedBytes":16706279320,"gc":[1073,716,716],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28560,"sharedPasses":7140,"driverPasses":7140,"browserPasses":7140}
|
||||
{"cycle":3580,"elapsedSeconds":4757.2517002,"utc":"2026-11-10T19:04:02.3755512Z","WorkingSet64":137400320,"PrivateMemorySize64":248283136,"managedBytes":4651936,"allocatedBytes":16752994160,"gc":[1076,718,718],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28640,"sharedPasses":7160,"driverPasses":7160,"browserPasses":7160}
|
||||
{"cycle":3590,"elapsedSeconds":4770.4598148,"utc":"2026-11-10T19:04:15.5798294Z","WorkingSet64":137400320,"PrivateMemorySize64":248283136,"managedBytes":4591552,"allocatedBytes":16799682856,"gc":[1079,720,720],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28720,"sharedPasses":7180,"driverPasses":7180,"browserPasses":7180}
|
||||
{"cycle":3600,"elapsedSeconds":4783.663336,"utc":"2026-11-10T19:04:28.7863751Z","WorkingSet64":137400320,"PrivateMemorySize64":248283136,"managedBytes":4635320,"allocatedBytes":16846434896,"gc":[1082,722,722],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28800,"sharedPasses":7200,"driverPasses":7200,"browserPasses":7200}
|
||||
{"cycle":3610,"elapsedSeconds":4796.8948164,"utc":"2026-11-10T19:04:42.0122819Z","WorkingSet64":137400320,"PrivateMemorySize64":248283136,"managedBytes":4643400,"allocatedBytes":16893143672,"gc":[1085,724,724],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28880,"sharedPasses":7220,"driverPasses":7220,"browserPasses":7220}
|
||||
{"cycle":3620,"elapsedSeconds":4810.139686,"utc":"2026-11-10T19:04:55.2710629Z","WorkingSet64":137535488,"PrivateMemorySize64":248283136,"managedBytes":4652376,"allocatedBytes":16940839752,"gc":[1088,726,726],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":28960,"sharedPasses":7240,"driverPasses":7240,"browserPasses":7240}
|
||||
{"cycle":3630,"elapsedSeconds":4823.3174498,"utc":"2026-11-10T19:05:08.4414838Z","WorkingSet64":137535488,"PrivateMemorySize64":248283136,"managedBytes":4652000,"allocatedBytes":16987565000,"gc":[1091,728,728],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29040,"sharedPasses":7260,"driverPasses":7260,"browserPasses":7260}
|
||||
{"cycle":3640,"elapsedSeconds":4836.5390828,"utc":"2026-11-10T19:05:21.6663296Z","WorkingSet64":137535488,"PrivateMemorySize64":248283136,"managedBytes":4592248,"allocatedBytes":17034280824,"gc":[1094,730,730],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29120,"sharedPasses":7280,"driverPasses":7280,"browserPasses":7280}
|
||||
{"cycle":3650,"elapsedSeconds":4849.7265939,"utc":"2026-11-10T19:05:34.8471528Z","WorkingSet64":137256960,"PrivateMemorySize64":248283136,"managedBytes":4584064,"allocatedBytes":17080982824,"gc":[1097,732,732],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29200,"sharedPasses":7300,"driverPasses":7300,"browserPasses":7300}
|
||||
{"cycle":3660,"elapsedSeconds":4863.1091391,"utc":"2026-11-10T19:05:48.2355383Z","WorkingSet64":137256960,"PrivateMemorySize64":248283136,"managedBytes":4592568,"allocatedBytes":17127699288,"gc":[1100,734,734],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29280,"sharedPasses":7320,"driverPasses":7320,"browserPasses":7320}
|
||||
{"cycle":3670,"elapsedSeconds":4876.4371056,"utc":"2026-11-10T19:06:01.5555912Z","WorkingSet64":137646080,"PrivateMemorySize64":248283136,"managedBytes":4654392,"allocatedBytes":17174484720,"gc":[1103,736,736],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29360,"sharedPasses":7340,"driverPasses":7340,"browserPasses":7340}
|
||||
{"cycle":3680,"elapsedSeconds":4889.6431798,"utc":"2026-11-10T19:06:14.7616703Z","WorkingSet64":137719808,"PrivateMemorySize64":248283136,"managedBytes":4651864,"allocatedBytes":17221191664,"gc":[1106,738,738],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29440,"sharedPasses":7360,"driverPasses":7360,"browserPasses":7360}
|
||||
{"cycle":3690,"elapsedSeconds":4902.8281565,"utc":"2026-11-10T19:06:27.957358Z","WorkingSet64":137101312,"PrivateMemorySize64":248303616,"managedBytes":4775576,"allocatedBytes":17268040424,"gc":[1109,740,740],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29520,"sharedPasses":7380,"driverPasses":7380,"browserPasses":7380}
|
||||
{"cycle":3700,"elapsedSeconds":4916.9700826,"utc":"2026-11-10T19:06:42.0889673Z","WorkingSet64":124518400,"PrivateMemorySize64":235720704,"managedBytes":4059920,"allocatedBytes":17314749104,"gc":[1112,742,742],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29600,"sharedPasses":7400,"driverPasses":7400,"browserPasses":7400}
|
||||
{"cycle":3710,"elapsedSeconds":4930.565824,"utc":"2026-11-10T19:06:55.6911321Z","WorkingSet64":116129792,"PrivateMemorySize64":227332096,"managedBytes":4134952,"allocatedBytes":17362152240,"gc":[1115,744,744],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29680,"sharedPasses":7420,"driverPasses":7420,"browserPasses":7420}
|
||||
{"cycle":3720,"elapsedSeconds":4943.7746161,"utc":"2026-11-10T19:07:08.8920686Z","WorkingSet64":136949760,"PrivateMemorySize64":248373248,"managedBytes":4634312,"allocatedBytes":17409400576,"gc":[1119,746,746],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29760,"sharedPasses":7440,"driverPasses":7440,"browserPasses":7440}
|
||||
{"cycle":3730,"elapsedSeconds":4957.0853609,"utc":"2026-11-10T19:07:22.2037568Z","WorkingSet64":136994816,"PrivateMemorySize64":248303616,"managedBytes":4137120,"allocatedBytes":17456131480,"gc":[1122,748,748],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29840,"sharedPasses":7460,"driverPasses":7460,"browserPasses":7460}
|
||||
{"cycle":3740,"elapsedSeconds":4970.2387122,"utc":"2026-11-10T19:07:35.3656669Z","WorkingSet64":136990720,"PrivateMemorySize64":248283136,"managedBytes":4121416,"allocatedBytes":17503358312,"gc":[1125,750,750],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":29920,"sharedPasses":7480,"driverPasses":7480,"browserPasses":7480}
|
||||
{"cycle":3750,"elapsedSeconds":4983.4241664,"utc":"2026-11-10T19:07:48.5429981Z","WorkingSet64":110030848,"PrivateMemorySize64":231505920,"managedBytes":4047040,"allocatedBytes":17550491048,"gc":[1128,752,752],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30000,"sharedPasses":7500,"driverPasses":7500,"browserPasses":7500}
|
||||
{"cycle":3760,"elapsedSeconds":4996.6297597,"utc":"2026-11-10T19:08:01.7515976Z","WorkingSet64":110759936,"PrivateMemorySize64":231370752,"managedBytes":4126712,"allocatedBytes":17597831216,"gc":[1131,754,754],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30080,"sharedPasses":7520,"driverPasses":7520,"browserPasses":7520}
|
||||
{"cycle":3770,"elapsedSeconds":5009.807343,"utc":"2026-11-10T19:08:14.9314294Z","WorkingSet64":114229248,"PrivateMemorySize64":234778624,"managedBytes":3990440,"allocatedBytes":17645089208,"gc":[1134,756,756],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30160,"sharedPasses":7540,"driverPasses":7540,"browserPasses":7540}
|
||||
{"cycle":3780,"elapsedSeconds":5022.9974358,"utc":"2026-11-10T19:08:28.118887Z","WorkingSet64":118804480,"PrivateMemorySize64":239341568,"managedBytes":4126312,"allocatedBytes":17692512680,"gc":[1137,758,758],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30240,"sharedPasses":7560,"driverPasses":7560,"browserPasses":7560}
|
||||
{"cycle":3790,"elapsedSeconds":5036.1678719,"utc":"2026-11-10T19:08:41.2886046Z","WorkingSet64":113438720,"PrivateMemorySize64":234778624,"managedBytes":3983752,"allocatedBytes":17739641736,"gc":[1140,760,760],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30320,"sharedPasses":7580,"driverPasses":7580,"browserPasses":7580}
|
||||
{"cycle":3800,"elapsedSeconds":5049.3879165,"utc":"2026-11-10T19:08:54.5088568Z","WorkingSet64":117698560,"PrivateMemorySize64":239058944,"managedBytes":4057200,"allocatedBytes":17786981520,"gc":[1143,762,762],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30400,"sharedPasses":7600,"driverPasses":7600,"browserPasses":7600}
|
||||
{"cycle":3810,"elapsedSeconds":5062.5706221,"utc":"2026-11-10T19:09:07.6932094Z","WorkingSet64":113373184,"PrivateMemorySize64":234733568,"managedBytes":3925728,"allocatedBytes":17834219336,"gc":[1146,764,764],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30480,"sharedPasses":7620,"driverPasses":7620,"browserPasses":7620}
|
||||
{"cycle":3820,"elapsedSeconds":5075.7628267,"utc":"2026-11-10T19:09:20.8853674Z","WorkingSet64":113299456,"PrivateMemorySize64":234979328,"managedBytes":4048560,"allocatedBytes":17881572704,"gc":[1149,766,766],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30560,"sharedPasses":7640,"driverPasses":7640,"browserPasses":7640}
|
||||
{"cycle":3830,"elapsedSeconds":5088.9765822,"utc":"2026-11-10T19:09:34.0970322Z","WorkingSet64":113799168,"PrivateMemorySize64":231604224,"managedBytes":4116720,"allocatedBytes":17928839568,"gc":[1152,768,768],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30640,"sharedPasses":7660,"driverPasses":7660,"browserPasses":7660}
|
||||
{"cycle":3840,"elapsedSeconds":5102.1627066,"utc":"2026-11-10T19:09:47.2830284Z","WorkingSet64":121585664,"PrivateMemorySize64":237752320,"managedBytes":4117912,"allocatedBytes":17975996528,"gc":[1155,770,770],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30720,"sharedPasses":7680,"driverPasses":7680,"browserPasses":7680}
|
||||
{"cycle":3850,"elapsedSeconds":5115.3504075,"utc":"2026-11-10T19:10:00.4711272Z","WorkingSet64":122200064,"PrivateMemorySize64":237752320,"managedBytes":4182968,"allocatedBytes":18024210640,"gc":[1158,772,772],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30800,"sharedPasses":7700,"driverPasses":7700,"browserPasses":7700}
|
||||
{"cycle":3860,"elapsedSeconds":5128.5365508,"utc":"2026-11-10T19:10:13.6572511Z","WorkingSet64":118472704,"PrivateMemorySize64":237469696,"managedBytes":4051336,"allocatedBytes":18071341240,"gc":[1161,774,774],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30880,"sharedPasses":7720,"driverPasses":7720,"browserPasses":7720}
|
||||
{"cycle":3870,"elapsedSeconds":5141.7550027,"utc":"2026-11-10T19:10:26.8761396Z","WorkingSet64":118669312,"PrivateMemorySize64":237666304,"managedBytes":4060480,"allocatedBytes":18118576056,"gc":[1164,776,776],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":30960,"sharedPasses":7740,"driverPasses":7740,"browserPasses":7740}
|
||||
{"cycle":3880,"elapsedSeconds":5154.950344,"utc":"2026-11-10T19:10:40.0716106Z","WorkingSet64":122941440,"PrivateMemorySize64":241926144,"managedBytes":4052472,"allocatedBytes":18165875200,"gc":[1167,778,778],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31040,"sharedPasses":7760,"driverPasses":7760,"browserPasses":7760}
|
||||
{"cycle":3890,"elapsedSeconds":5168.117364,"utc":"2026-11-10T19:10:53.2398938Z","WorkingSet64":117174272,"PrivateMemorySize64":237752320,"managedBytes":4141832,"allocatedBytes":18213113216,"gc":[1170,780,780],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31120,"sharedPasses":7780,"driverPasses":7780,"browserPasses":7780}
|
||||
{"cycle":3900,"elapsedSeconds":5181.3372804,"utc":"2026-11-10T19:11:06.4597396Z","WorkingSet64":120975360,"PrivateMemorySize64":241557504,"managedBytes":3930784,"allocatedBytes":18260351928,"gc":[1173,782,782],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31200,"sharedPasses":7800,"driverPasses":7800,"browserPasses":7800}
|
||||
{"cycle":3910,"elapsedSeconds":5194.5465198,"utc":"2026-11-10T19:11:19.6666227Z","WorkingSet64":116862976,"PrivateMemorySize64":237445120,"managedBytes":4012488,"allocatedBytes":18307701248,"gc":[1176,784,784],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31280,"sharedPasses":7820,"driverPasses":7820,"browserPasses":7820}
|
||||
{"cycle":3920,"elapsedSeconds":5207.7307735,"utc":"2026-11-10T19:11:32.8530313Z","WorkingSet64":116346880,"PrivateMemorySize64":237887488,"managedBytes":4129120,"allocatedBytes":18355012024,"gc":[1179,786,786],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31360,"sharedPasses":7840,"driverPasses":7840,"browserPasses":7840}
|
||||
{"cycle":3930,"elapsedSeconds":5220.9260914,"utc":"2026-11-10T19:11:46.0462522Z","WorkingSet64":112140288,"PrivateMemorySize64":233680896,"managedBytes":3987264,"allocatedBytes":18402181928,"gc":[1182,788,788],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31440,"sharedPasses":7860,"driverPasses":7860,"browserPasses":7860}
|
||||
{"cycle":3940,"elapsedSeconds":5234.1043659,"utc":"2026-11-10T19:11:59.2333062Z","WorkingSet64":116195328,"PrivateMemorySize64":237756416,"managedBytes":4131424,"allocatedBytes":18449637448,"gc":[1185,790,790],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31520,"sharedPasses":7880,"driverPasses":7880,"browserPasses":7880}
|
||||
{"cycle":3950,"elapsedSeconds":5247.2809462,"utc":"2026-11-10T19:12:12.4014496Z","WorkingSet64":116195328,"PrivateMemorySize64":237756416,"managedBytes":4130480,"allocatedBytes":18496919424,"gc":[1188,792,792],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31600,"sharedPasses":7900,"driverPasses":7900,"browserPasses":7900}
|
||||
{"cycle":3960,"elapsedSeconds":5260.4711176,"utc":"2026-11-10T19:12:25.592345Z","WorkingSet64":115834880,"PrivateMemorySize64":237543424,"managedBytes":3986744,"allocatedBytes":18544086800,"gc":[1191,794,794],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31680,"sharedPasses":7920,"driverPasses":7920,"browserPasses":7920}
|
||||
{"cycle":3970,"elapsedSeconds":5273.6560463,"utc":"2026-11-10T19:12:38.7765168Z","WorkingSet64":116748288,"PrivateMemorySize64":238514176,"managedBytes":4191968,"allocatedBytes":18591503240,"gc":[1194,796,796],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31760,"sharedPasses":7940,"driverPasses":7940,"browserPasses":7940}
|
||||
{"cycle":3980,"elapsedSeconds":5287.0780618,"utc":"2026-11-10T19:12:52.2033699Z","WorkingSet64":120549376,"PrivateMemorySize64":238456832,"managedBytes":3933064,"allocatedBytes":18638644256,"gc":[1197,798,798],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31840,"sharedPasses":7960,"driverPasses":7960,"browserPasses":7960}
|
||||
{"cycle":3990,"elapsedSeconds":5300.2386385,"utc":"2026-11-10T19:13:05.35981Z","WorkingSet64":116281344,"PrivateMemorySize64":238809088,"managedBytes":4059496,"allocatedBytes":18686045672,"gc":[1200,800,800],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":31920,"sharedPasses":7980,"driverPasses":7980,"browserPasses":7980}
|
||||
{"cycle":4000,"elapsedSeconds":5313.4321402,"utc":"2026-11-10T19:13:18.5522027Z","WorkingSet64":115970048,"PrivateMemorySize64":238477312,"managedBytes":3986720,"allocatedBytes":18733363784,"gc":[1203,802,802],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32000,"sharedPasses":8000,"driverPasses":8000,"browserPasses":8000}
|
||||
{"cycle":4010,"elapsedSeconds":5326.6204532,"utc":"2026-11-10T19:13:31.7406049Z","WorkingSet64":120508416,"PrivateMemorySize64":243015680,"managedBytes":4050832,"allocatedBytes":18780637368,"gc":[1206,804,804],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32080,"sharedPasses":8020,"driverPasses":8020,"browserPasses":8020}
|
||||
{"cycle":4020,"elapsedSeconds":5339.8009168,"utc":"2026-11-10T19:13:44.9208525Z","WorkingSet64":116535296,"PrivateMemorySize64":239058944,"managedBytes":3999648,"allocatedBytes":18828062416,"gc":[1209,806,806],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32160,"sharedPasses":8040,"driverPasses":8040,"browserPasses":8040}
|
||||
{"cycle":4030,"elapsedSeconds":5352.99487,"utc":"2026-11-10T19:13:58.1154394Z","WorkingSet64":116318208,"PrivateMemorySize64":238993408,"managedBytes":4065696,"allocatedBytes":18875461184,"gc":[1212,808,808],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32240,"sharedPasses":8060,"driverPasses":8060,"browserPasses":8060}
|
||||
{"cycle":4040,"elapsedSeconds":5366.1798216,"utc":"2026-11-10T19:14:11.2997745Z","WorkingSet64":120360960,"PrivateMemorySize64":243036160,"managedBytes":4065416,"allocatedBytes":18922683736,"gc":[1215,810,810],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32320,"sharedPasses":8080,"driverPasses":8080,"browserPasses":8080}
|
||||
{"cycle":4050,"elapsedSeconds":5379.3735217,"utc":"2026-11-10T19:14:24.4955573Z","WorkingSet64":115818496,"PrivateMemorySize64":238473216,"managedBytes":3993632,"allocatedBytes":18969993968,"gc":[1218,812,812],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32400,"sharedPasses":8100,"driverPasses":8100,"browserPasses":8100}
|
||||
{"cycle":4060,"elapsedSeconds":5392.4722436,"utc":"2026-11-10T19:14:37.5990338Z","WorkingSet64":120197120,"PrivateMemorySize64":243015680,"managedBytes":4075624,"allocatedBytes":19017373272,"gc":[1221,814,814],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32480,"sharedPasses":8120,"driverPasses":8120,"browserPasses":8120}
|
||||
{"cycle":4070,"elapsedSeconds":5405.651646,"utc":"2026-11-10T19:14:50.7730584Z","WorkingSet64":116289536,"PrivateMemorySize64":238841856,"managedBytes":4146208,"allocatedBytes":19065570184,"gc":[1224,816,816],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32560,"sharedPasses":8140,"driverPasses":8140,"browserPasses":8140}
|
||||
{"cycle":4080,"elapsedSeconds":5418.8294594,"utc":"2026-11-10T19:15:03.9504794Z","WorkingSet64":115945472,"PrivateMemorySize64":238477312,"managedBytes":3987144,"allocatedBytes":19112715504,"gc":[1227,818,818],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32640,"sharedPasses":8160,"driverPasses":8160,"browserPasses":8160}
|
||||
{"cycle":4090,"elapsedSeconds":5432.0374034,"utc":"2026-11-10T19:15:17.1601803Z","WorkingSet64":119640064,"PrivateMemorySize64":243015680,"managedBytes":4117304,"allocatedBytes":19160028664,"gc":[1230,820,820],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32720,"sharedPasses":8180,"driverPasses":8180,"browserPasses":8180}
|
||||
{"cycle":4100,"elapsedSeconds":5445.2179978,"utc":"2026-11-10T19:15:30.3375728Z","WorkingSet64":115707904,"PrivateMemorySize64":238841856,"managedBytes":4065072,"allocatedBytes":19207398240,"gc":[1233,822,822],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32800,"sharedPasses":8200,"driverPasses":8200,"browserPasses":8200}
|
||||
{"cycle":4110,"elapsedSeconds":5458.5514867,"utc":"2026-11-10T19:15:43.6738027Z","WorkingSet64":115470336,"PrivateMemorySize64":238653440,"managedBytes":4008096,"allocatedBytes":19254725512,"gc":[1236,824,824],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32880,"sharedPasses":8220,"driverPasses":8220,"browserPasses":8220}
|
||||
{"cycle":4120,"elapsedSeconds":5471.7379288,"utc":"2026-11-10T19:15:56.8593109Z","WorkingSet64":119562240,"PrivateMemorySize64":242696192,"managedBytes":4000688,"allocatedBytes":19302079136,"gc":[1239,826,826],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":32960,"sharedPasses":8240,"driverPasses":8240,"browserPasses":8240}
|
||||
{"cycle":4130,"elapsedSeconds":5484.9562507,"utc":"2026-11-10T19:16:10.0781878Z","WorkingSet64":112144384,"PrivateMemorySize64":238743552,"managedBytes":4117832,"allocatedBytes":19349475504,"gc":[1242,828,828],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33040,"sharedPasses":8260,"driverPasses":8260,"browserPasses":8260}
|
||||
{"cycle":4140,"elapsedSeconds":5498.1464981,"utc":"2026-11-10T19:16:23.2672877Z","WorkingSet64":112189440,"PrivateMemorySize64":238809088,"managedBytes":4118056,"allocatedBytes":19396632144,"gc":[1245,830,830],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33120,"sharedPasses":8280,"driverPasses":8280,"browserPasses":8280}
|
||||
{"cycle":4150,"elapsedSeconds":5511.3163326,"utc":"2026-11-10T19:16:36.4363444Z","WorkingSet64":119017472,"PrivateMemorySize64":238809088,"managedBytes":4051480,"allocatedBytes":19443932616,"gc":[1248,832,832],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33200,"sharedPasses":8300,"driverPasses":8300,"browserPasses":8300}
|
||||
{"cycle":4160,"elapsedSeconds":5524.5309388,"utc":"2026-11-10T19:16:49.6556238Z","WorkingSet64":118751232,"PrivateMemorySize64":238542848,"managedBytes":4052120,"allocatedBytes":19491166240,"gc":[1251,834,834],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33280,"sharedPasses":8320,"driverPasses":8320,"browserPasses":8320}
|
||||
{"cycle":4170,"elapsedSeconds":5537.7220072,"utc":"2026-11-10T19:17:02.8451387Z","WorkingSet64":118878208,"PrivateMemorySize64":238739456,"managedBytes":4117344,"allocatedBytes":19538501200,"gc":[1254,836,836],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33360,"sharedPasses":8340,"driverPasses":8340,"browserPasses":8340}
|
||||
{"cycle":4180,"elapsedSeconds":5550.9211684,"utc":"2026-11-10T19:17:16.0417485Z","WorkingSet64":118636544,"PrivateMemorySize64":238428160,"managedBytes":3938976,"allocatedBytes":19585669400,"gc":[1257,838,838],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33440,"sharedPasses":8360,"driverPasses":8360,"browserPasses":8360}
|
||||
{"cycle":4190,"elapsedSeconds":5564.0375684,"utc":"2026-11-10T19:17:29.1581926Z","WorkingSet64":122945536,"PrivateMemorySize64":242737152,"managedBytes":4052080,"allocatedBytes":19633028448,"gc":[1260,840,840],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33520,"sharedPasses":8380,"driverPasses":8380,"browserPasses":8380}
|
||||
{"cycle":4200,"elapsedSeconds":5577.243114,"utc":"2026-11-10T19:17:42.3638545Z","WorkingSet64":115806208,"PrivateMemorySize64":238678016,"managedBytes":4054832,"allocatedBytes":19680330576,"gc":[1263,842,842],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33600,"sharedPasses":8400,"driverPasses":8400,"browserPasses":8400}
|
||||
{"cycle":4210,"elapsedSeconds":5590.4732,"utc":"2026-11-10T19:17:55.5936071Z","WorkingSet64":112427008,"PrivateMemorySize64":235294720,"managedBytes":4182696,"allocatedBytes":19727670840,"gc":[1266,844,844],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33680,"sharedPasses":8420,"driverPasses":8420,"browserPasses":8420}
|
||||
{"cycle":4220,"elapsedSeconds":5603.6574161,"utc":"2026-11-10T19:18:08.7779418Z","WorkingSet64":118849536,"PrivateMemorySize64":238821376,"managedBytes":4118560,"allocatedBytes":19774876072,"gc":[1269,846,846],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33760,"sharedPasses":8440,"driverPasses":8440,"browserPasses":8440}
|
||||
{"cycle":4230,"elapsedSeconds":5616.9644296,"utc":"2026-11-10T19:18:22.0853634Z","WorkingSet64":116146176,"PrivateMemorySize64":238542848,"managedBytes":4052248,"allocatedBytes":19822067312,"gc":[1272,848,848],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33840,"sharedPasses":8460,"driverPasses":8460,"browserPasses":8460}
|
||||
{"cycle":4240,"elapsedSeconds":5630.1527451,"utc":"2026-11-10T19:18:35.2735179Z","WorkingSet64":120274944,"PrivateMemorySize64":242671616,"managedBytes":3987312,"allocatedBytes":19869276368,"gc":[1275,850,850],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":33920,"sharedPasses":8480,"driverPasses":8480,"browserPasses":8480}
|
||||
{"cycle":4250,"elapsedSeconds":5643.258075,"utc":"2026-11-10T19:18:48.3788452Z","WorkingSet64":120619008,"PrivateMemorySize64":243036160,"managedBytes":4130328,"allocatedBytes":19916603080,"gc":[1278,852,852],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34000,"sharedPasses":8500,"driverPasses":8500,"browserPasses":8500}
|
||||
{"cycle":4260,"elapsedSeconds":5656.4796106,"utc":"2026-11-10T19:19:01.6002197Z","WorkingSet64":116424704,"PrivateMemorySize64":238821376,"managedBytes":3986568,"allocatedBytes":19963759592,"gc":[1281,854,854],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34080,"sharedPasses":8520,"driverPasses":8520,"browserPasses":8520}
|
||||
{"cycle":4270,"elapsedSeconds":5669.646909,"utc":"2026-11-10T19:19:14.768944Z","WorkingSet64":112164864,"PrivateMemorySize64":234565632,"managedBytes":4051192,"allocatedBytes":20011050336,"gc":[1284,856,856],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34160,"sharedPasses":8540,"driverPasses":8540,"browserPasses":8540}
|
||||
{"cycle":4280,"elapsedSeconds":5682.8394648,"utc":"2026-11-10T19:19:27.9626123Z","WorkingSet64":116408320,"PrivateMemorySize64":238804992,"managedBytes":4117976,"allocatedBytes":20058264848,"gc":[1287,858,858],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34240,"sharedPasses":8560,"driverPasses":8560,"browserPasses":8560}
|
||||
{"cycle":4290,"elapsedSeconds":5696.1424054,"utc":"2026-11-10T19:19:41.265842Z","WorkingSet64":116006912,"PrivateMemorySize64":238411776,"managedBytes":3920976,"allocatedBytes":20105484200,"gc":[1290,860,860],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34320,"sharedPasses":8580,"driverPasses":8580,"browserPasses":8580}
|
||||
{"cycle":4300,"elapsedSeconds":5709.4636964,"utc":"2026-11-10T19:19:54.5865621Z","WorkingSet64":114135040,"PrivateMemorySize64":238739456,"managedBytes":3986864,"allocatedBytes":20153830552,"gc":[1293,862,862],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34400,"sharedPasses":8600,"driverPasses":8600,"browserPasses":8600}
|
||||
{"cycle":4310,"elapsedSeconds":5722.6223838,"utc":"2026-11-10T19:20:07.7425961Z","WorkingSet64":113922048,"PrivateMemorySize64":238477312,"managedBytes":3986584,"allocatedBytes":20201120472,"gc":[1296,864,864],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34480,"sharedPasses":8620,"driverPasses":8620,"browserPasses":8620}
|
||||
{"cycle":4320,"elapsedSeconds":5735.8363918,"utc":"2026-11-10T19:20:20.9579718Z","WorkingSet64":118927360,"PrivateMemorySize64":238542848,"managedBytes":4052440,"allocatedBytes":20248450960,"gc":[1299,866,866],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34560,"sharedPasses":8640,"driverPasses":8640,"browserPasses":8640}
|
||||
{"cycle":4330,"elapsedSeconds":5749.0586465,"utc":"2026-11-10T19:20:34.1804388Z","WorkingSet64":122449920,"PrivateMemorySize64":242606080,"managedBytes":3921688,"allocatedBytes":20295685776,"gc":[1302,868,868],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34640,"sharedPasses":8660,"driverPasses":8660,"browserPasses":8660}
|
||||
{"cycle":4340,"elapsedSeconds":5762.2892765,"utc":"2026-11-10T19:20:47.4098321Z","WorkingSet64":118632448,"PrivateMemorySize64":238804992,"managedBytes":4051800,"allocatedBytes":20343032120,"gc":[1305,870,870],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34720,"sharedPasses":8680,"driverPasses":8680,"browserPasses":8680}
|
||||
{"cycle":4350,"elapsedSeconds":5775.4195846,"utc":"2026-11-10T19:21:00.5412352Z","WorkingSet64":122613760,"PrivateMemorySize64":242688000,"managedBytes":4010408,"allocatedBytes":20390269328,"gc":[1308,872,872],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34800,"sharedPasses":8700,"driverPasses":8700,"browserPasses":8700}
|
||||
{"cycle":4360,"elapsedSeconds":5788.4635996,"utc":"2026-11-10T19:21:13.5854732Z","WorkingSet64":122531840,"PrivateMemorySize64":242606080,"managedBytes":3929264,"allocatedBytes":20437564128,"gc":[1311,874,874],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34880,"sharedPasses":8720,"driverPasses":8720,"browserPasses":8720}
|
||||
{"cycle":4370,"elapsedSeconds":5801.6784919,"utc":"2026-11-10T19:21:26.8009392Z","WorkingSet64":118317056,"PrivateMemorySize64":238804992,"managedBytes":4115120,"allocatedBytes":20484954072,"gc":[1314,876,876],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":34960,"sharedPasses":8740,"driverPasses":8740,"browserPasses":8740}
|
||||
{"cycle":4380,"elapsedSeconds":5814.8853536,"utc":"2026-11-10T19:21:40.0060554Z","WorkingSet64":122527744,"PrivateMemorySize64":243015680,"managedBytes":4117160,"allocatedBytes":20532150552,"gc":[1317,878,878],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35040,"sharedPasses":8760,"driverPasses":8760,"browserPasses":8760}
|
||||
{"cycle":4390,"elapsedSeconds":5828.0861403,"utc":"2026-11-10T19:21:53.2062004Z","WorkingSet64":118050816,"PrivateMemorySize64":238559232,"managedBytes":4059520,"allocatedBytes":20579321328,"gc":[1320,880,880],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35120,"sharedPasses":8780,"driverPasses":8780,"browserPasses":8780}
|
||||
{"cycle":4400,"elapsedSeconds":5841.3106131,"utc":"2026-11-10T19:22:06.4312153Z","WorkingSet64":119357440,"PrivateMemorySize64":238800896,"managedBytes":4059464,"allocatedBytes":20626569768,"gc":[1323,882,882],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35200,"sharedPasses":8800,"driverPasses":8800,"browserPasses":8800}
|
||||
{"cycle":4410,"elapsedSeconds":5854.50526,"utc":"2026-11-10T19:22:19.6298345Z","WorkingSet64":119046144,"PrivateMemorySize64":238411776,"managedBytes":3920552,"allocatedBytes":20673780112,"gc":[1326,884,884],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35280,"sharedPasses":8820,"driverPasses":8820,"browserPasses":8820}
|
||||
{"cycle":4420,"elapsedSeconds":5867.6676296,"utc":"2026-11-10T19:22:32.7931075Z","WorkingSet64":119455744,"PrivateMemorySize64":238821376,"managedBytes":4116600,"allocatedBytes":20721190608,"gc":[1329,886,886],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35360,"sharedPasses":8840,"driverPasses":8840,"browserPasses":8840}
|
||||
{"cycle":4430,"elapsedSeconds":5880.9144492,"utc":"2026-11-10T19:22:46.0375909Z","WorkingSet64":119111680,"PrivateMemorySize64":238477312,"managedBytes":3986256,"allocatedBytes":20768362072,"gc":[1332,888,888],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35440,"sharedPasses":8860,"driverPasses":8860,"browserPasses":8860}
|
||||
{"cycle":4440,"elapsedSeconds":5894.200753,"utc":"2026-11-10T19:22:59.3234916Z","WorkingSet64":119373824,"PrivateMemorySize64":238804992,"managedBytes":4051808,"allocatedBytes":20815638800,"gc":[1335,890,890],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35520,"sharedPasses":8880,"driverPasses":8880,"browserPasses":8880}
|
||||
{"cycle":4450,"elapsedSeconds":5907.41241,"utc":"2026-11-10T19:23:12.5342293Z","WorkingSet64":119373824,"PrivateMemorySize64":238804992,"managedBytes":4117192,"allocatedBytes":20862865904,"gc":[1338,892,892],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35600,"sharedPasses":8900,"driverPasses":8900,"browserPasses":8900}
|
||||
{"cycle":4460,"elapsedSeconds":5920.5786488,"utc":"2026-11-10T19:23:25.6999325Z","WorkingSet64":119373824,"PrivateMemorySize64":238825472,"managedBytes":4204752,"allocatedBytes":20910245512,"gc":[1341,894,894],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35680,"sharedPasses":8920,"driverPasses":8920,"browserPasses":8920}
|
||||
{"cycle":4470,"elapsedSeconds":5933.783289,"utc":"2026-11-10T19:23:38.9076636Z","WorkingSet64":117010432,"PrivateMemorySize64":238477312,"managedBytes":3986800,"allocatedBytes":20957336520,"gc":[1344,896,896],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35760,"sharedPasses":8940,"driverPasses":8940,"browserPasses":8940}
|
||||
{"cycle":4480,"elapsedSeconds":5946.9322959,"utc":"2026-11-10T19:23:52.0538473Z","WorkingSet64":121221120,"PrivateMemorySize64":242737152,"managedBytes":4060264,"allocatedBytes":21004731368,"gc":[1347,898,898],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35840,"sharedPasses":8960,"driverPasses":8960,"browserPasses":8960}
|
||||
{"cycle":4490,"elapsedSeconds":5960.1149296,"utc":"2026-11-10T19:24:05.2362333Z","WorkingSet64":117338112,"PrivateMemorySize64":238804992,"managedBytes":4117664,"allocatedBytes":21051919344,"gc":[1350,900,900],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":35920,"sharedPasses":8980,"driverPasses":8980,"browserPasses":8980}
|
||||
{"cycle":4500,"elapsedSeconds":5973.3097143,"utc":"2026-11-10T19:24:18.4304225Z","WorkingSet64":116944896,"PrivateMemorySize64":242671616,"managedBytes":3995088,"allocatedBytes":21099166368,"gc":[1353,902,902],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36000,"sharedPasses":9000,"driverPasses":9000,"browserPasses":9000}
|
||||
{"cycle":4510,"elapsedSeconds":5986.4949925,"utc":"2026-11-10T19:24:31.6217934Z","WorkingSet64":113094656,"PrivateMemorySize64":238841856,"managedBytes":4136848,"allocatedBytes":21146602576,"gc":[1356,904,904],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36080,"sharedPasses":9020,"driverPasses":9020,"browserPasses":9020}
|
||||
{"cycle":4520,"elapsedSeconds":5999.6813214,"utc":"2026-11-10T19:24:44.804008Z","WorkingSet64":112750592,"PrivateMemorySize64":238477312,"managedBytes":3993880,"allocatedBytes":21193721232,"gc":[1359,906,906],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36160,"sharedPasses":9040,"driverPasses":9040,"browserPasses":9040}
|
||||
{"cycle":4530,"elapsedSeconds":6013.0794661,"utc":"2026-11-10T19:24:58.2004566Z","WorkingSet64":112988160,"PrivateMemorySize64":238448640,"managedBytes":3989448,"allocatedBytes":21241965352,"gc":[1362,908,908],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36240,"sharedPasses":9060,"driverPasses":9060,"browserPasses":9060}
|
||||
{"cycle":4540,"elapsedSeconds":6026.2845092,"utc":"2026-11-10T19:25:11.4070276Z","WorkingSet64":113311744,"PrivateMemorySize64":238796800,"managedBytes":4124584,"allocatedBytes":21289271104,"gc":[1365,910,910],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36320,"sharedPasses":9080,"driverPasses":9080,"browserPasses":9080}
|
||||
{"cycle":4550,"elapsedSeconds":6039.4915966,"utc":"2026-11-10T19:25:24.6129566Z","WorkingSet64":117800960,"PrivateMemorySize64":238841856,"managedBytes":4083408,"allocatedBytes":21336391544,"gc":[1368,912,912],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36400,"sharedPasses":9100,"driverPasses":9100,"browserPasses":9100}
|
||||
{"cycle":4560,"elapsedSeconds":6052.6990044,"utc":"2026-11-10T19:25:37.8198535Z","WorkingSet64":117518336,"PrivateMemorySize64":238538752,"managedBytes":4058512,"allocatedBytes":21383573296,"gc":[1371,914,914],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36480,"sharedPasses":9120,"driverPasses":9120,"browserPasses":9120}
|
||||
{"cycle":4570,"elapsedSeconds":6065.9007795,"utc":"2026-11-10T19:25:51.0221451Z","WorkingSet64":121528320,"PrivateMemorySize64":243015680,"managedBytes":4141088,"allocatedBytes":21430825480,"gc":[1374,916,916],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36560,"sharedPasses":9140,"driverPasses":9140,"browserPasses":9140}
|
||||
{"cycle":4580,"elapsedSeconds":6079.0842576,"utc":"2026-11-10T19:26:04.2090215Z","WorkingSet64":117002240,"PrivateMemorySize64":238538752,"managedBytes":4058744,"allocatedBytes":21477997224,"gc":[1377,918,918],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36640,"sharedPasses":9160,"driverPasses":9160,"browserPasses":9160}
|
||||
{"cycle":4590,"elapsedSeconds":6092.275871,"utc":"2026-11-10T19:26:17.3968782Z","WorkingSet64":117301248,"PrivateMemorySize64":238800896,"managedBytes":4059496,"allocatedBytes":21525255696,"gc":[1380,920,920],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36720,"sharedPasses":9180,"driverPasses":9180,"browserPasses":9180}
|
||||
{"cycle":4600,"elapsedSeconds":6105.4664507,"utc":"2026-11-10T19:26:30.5893728Z","WorkingSet64":117301248,"PrivateMemorySize64":238800896,"managedBytes":4058936,"allocatedBytes":21572502848,"gc":[1383,922,922],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36800,"sharedPasses":9200,"driverPasses":9200,"browserPasses":9200}
|
||||
{"cycle":4610,"elapsedSeconds":6118.7135893,"utc":"2026-11-10T19:26:43.834836Z","WorkingSet64":115064832,"PrivateMemorySize64":238473216,"managedBytes":3993272,"allocatedBytes":21619832216,"gc":[1386,924,924],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36880,"sharedPasses":9220,"driverPasses":9220,"browserPasses":9220}
|
||||
{"cycle":4620,"elapsedSeconds":6131.9146606,"utc":"2026-11-10T19:26:57.0385977Z","WorkingSet64":115138560,"PrivateMemorySize64":238538752,"managedBytes":4059368,"allocatedBytes":21667064424,"gc":[1389,926,926],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":36960,"sharedPasses":9240,"driverPasses":9240,"browserPasses":9240}
|
||||
{"cycle":4630,"elapsedSeconds":6145.07493,"utc":"2026-11-10T19:27:10.1955085Z","WorkingSet64":115400704,"PrivateMemorySize64":238800896,"managedBytes":4124672,"allocatedBytes":21714330904,"gc":[1392,928,928],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37040,"sharedPasses":9260,"driverPasses":9260,"browserPasses":9260}
|
||||
{"cycle":4640,"elapsedSeconds":6158.3206657,"utc":"2026-11-10T19:27:23.4544591Z","WorkingSet64":116514816,"PrivateMemorySize64":243015680,"managedBytes":4074752,"allocatedBytes":21761491936,"gc":[1395,930,930],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37120,"sharedPasses":9280,"driverPasses":9280,"browserPasses":9280}
|
||||
{"cycle":4650,"elapsedSeconds":6171.497499,"utc":"2026-11-10T19:27:36.6216647Z","WorkingSet64":117235712,"PrivateMemorySize64":243036160,"managedBytes":4138696,"allocatedBytes":21808716864,"gc":[1398,932,932],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37200,"sharedPasses":9300,"driverPasses":9300,"browserPasses":9300}
|
||||
{"cycle":4660,"elapsedSeconds":6184.8124801,"utc":"2026-11-10T19:27:49.938559Z","WorkingSet64":116957184,"PrivateMemorySize64":242696192,"managedBytes":3999488,"allocatedBytes":21855895072,"gc":[1401,934,934],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37280,"sharedPasses":9320,"driverPasses":9320,"browserPasses":9320}
|
||||
{"cycle":4670,"elapsedSeconds":6198.018103,"utc":"2026-11-10T19:28:03.1413054Z","WorkingSet64":112758784,"PrivateMemorySize64":238497792,"managedBytes":3998216,"allocatedBytes":21903194216,"gc":[1404,936,936],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37360,"sharedPasses":9340,"driverPasses":9340,"browserPasses":9340}
|
||||
{"cycle":4680,"elapsedSeconds":6211.1886598,"utc":"2026-11-10T19:28:16.3279143Z","WorkingSet64":113127424,"PrivateMemorySize64":238608384,"managedBytes":3992800,"allocatedBytes":21950465880,"gc":[1407,938,938],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37440,"sharedPasses":9360,"driverPasses":9360,"browserPasses":9360}
|
||||
{"cycle":4690,"elapsedSeconds":6224.3907958,"utc":"2026-11-10T19:28:29.5192565Z","WorkingSet64":109191168,"PrivateMemorySize64":234684416,"managedBytes":3928200,"allocatedBytes":21997768736,"gc":[1410,940,940],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37520,"sharedPasses":9380,"driverPasses":9380,"browserPasses":9380}
|
||||
{"cycle":4700,"elapsedSeconds":6237.6652159,"utc":"2026-11-10T19:28:42.78991Z","WorkingSet64":113373184,"PrivateMemorySize64":238821376,"managedBytes":4076504,"allocatedBytes":22045100088,"gc":[1413,942,942],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37600,"sharedPasses":9400,"driverPasses":9400,"browserPasses":9400}
|
||||
{"cycle":4710,"elapsedSeconds":6250.8680635,"utc":"2026-11-10T19:28:55.9972871Z","WorkingSet64":112799744,"PrivateMemorySize64":238407680,"managedBytes":3928536,"allocatedBytes":22092321136,"gc":[1416,944,944],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37680,"sharedPasses":9420,"driverPasses":9420,"browserPasses":9420}
|
||||
{"cycle":4720,"elapsedSeconds":6263.9673657,"utc":"2026-11-10T19:29:09.0921219Z","WorkingSet64":117030912,"PrivateMemorySize64":242606080,"managedBytes":3920824,"allocatedBytes":22139649760,"gc":[1419,946,946],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37760,"sharedPasses":9440,"driverPasses":9440,"browserPasses":9440}
|
||||
{"cycle":4730,"elapsedSeconds":6277.1654307,"utc":"2026-11-10T19:29:22.2885143Z","WorkingSet64":112898048,"PrivateMemorySize64":238473216,"managedBytes":3993776,"allocatedBytes":22187080472,"gc":[1422,948,948],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37840,"sharedPasses":9460,"driverPasses":9460,"browserPasses":9460}
|
||||
{"cycle":4740,"elapsedSeconds":6290.3636862,"utc":"2026-11-10T19:29:35.488547Z","WorkingSet64":113213440,"PrivateMemorySize64":238800896,"managedBytes":4125568,"allocatedBytes":22234324152,"gc":[1425,950,950],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":37920,"sharedPasses":9480,"driverPasses":9480,"browserPasses":9480}
|
||||
{"cycle":4750,"elapsedSeconds":6303.7261523,"utc":"2026-11-10T19:29:48.8488375Z","WorkingSet64":113274880,"PrivateMemorySize64":238411776,"managedBytes":3929424,"allocatedBytes":22282483392,"gc":[1428,952,952],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38000,"sharedPasses":9500,"driverPasses":9500,"browserPasses":9500}
|
||||
{"cycle":4760,"elapsedSeconds":6317.0165925,"utc":"2026-11-10T19:30:02.1409803Z","WorkingSet64":113676288,"PrivateMemorySize64":238804992,"managedBytes":4124344,"allocatedBytes":22329868424,"gc":[1431,954,954],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38080,"sharedPasses":9520,"driverPasses":9520,"browserPasses":9520}
|
||||
{"cycle":4770,"elapsedSeconds":6330.2058949,"utc":"2026-11-10T19:30:15.3267775Z","WorkingSet64":113676288,"PrivateMemorySize64":238804992,"managedBytes":4068088,"allocatedBytes":22376993912,"gc":[1434,956,956],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38160,"sharedPasses":9540,"driverPasses":9540,"browserPasses":9540}
|
||||
{"cycle":4780,"elapsedSeconds":6343.4448178,"utc":"2026-11-10T19:30:28.5659763Z","WorkingSet64":112865280,"PrivateMemorySize64":238825472,"managedBytes":4125280,"allocatedBytes":22424311448,"gc":[1437,958,958],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38240,"sharedPasses":9560,"driverPasses":9560,"browserPasses":9560}
|
||||
{"cycle":4790,"elapsedSeconds":6356.6536327,"utc":"2026-11-10T19:30:41.7775935Z","WorkingSet64":112865280,"PrivateMemorySize64":238432256,"managedBytes":3938040,"allocatedBytes":22471487088,"gc":[1440,960,960],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38320,"sharedPasses":9580,"driverPasses":9580,"browserPasses":9580}
|
||||
{"cycle":4800,"elapsedSeconds":6369.8412654,"utc":"2026-11-10T19:30:54.9784635Z","WorkingSet64":113262592,"PrivateMemorySize64":238546944,"managedBytes":3931112,"allocatedBytes":22518928560,"gc":[1443,962,962],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38400,"sharedPasses":9600,"driverPasses":9600,"browserPasses":9600}
|
||||
{"cycle":4810,"elapsedSeconds":6383.0050634,"utc":"2026-11-10T19:31:08.1344211Z","WorkingSet64":109965312,"PrivateMemorySize64":235368448,"managedBytes":4154640,"allocatedBytes":22566430632,"gc":[1446,964,964],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38480,"sharedPasses":9620,"driverPasses":9620,"browserPasses":9620}
|
||||
{"cycle":4820,"elapsedSeconds":6396.4128499,"utc":"2026-11-10T19:31:21.5470456Z","WorkingSet64":122699776,"PrivateMemorySize64":243056640,"managedBytes":4153752,"allocatedBytes":22613653672,"gc":[1449,966,966],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38560,"sharedPasses":9640,"driverPasses":9640,"browserPasses":9640}
|
||||
{"cycle":4830,"elapsedSeconds":6409.8899742,"utc":"2026-11-10T19:31:35.0148456Z","WorkingSet64":118222848,"PrivateMemorySize64":238538752,"managedBytes":4059152,"allocatedBytes":22660752464,"gc":[1452,968,968],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38640,"sharedPasses":9660,"driverPasses":9660,"browserPasses":9660}
|
||||
{"cycle":4840,"elapsedSeconds":6423.0769856,"utc":"2026-11-10T19:31:48.1984714Z","WorkingSet64":117592064,"PrivateMemorySize64":238489600,"managedBytes":4009600,"allocatedBytes":22707986512,"gc":[1455,970,970],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38720,"sharedPasses":9680,"driverPasses":9680,"browserPasses":9680}
|
||||
{"cycle":4850,"elapsedSeconds":6436.2743442,"utc":"2026-11-10T19:32:01.3946522Z","WorkingSet64":117641216,"PrivateMemorySize64":238538752,"managedBytes":4059072,"allocatedBytes":22755224496,"gc":[1458,972,972],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38800,"sharedPasses":9700,"driverPasses":9700,"browserPasses":9700}
|
||||
{"cycle":4860,"elapsedSeconds":6449.4308089,"utc":"2026-11-10T19:32:14.5532745Z","WorkingSet64":117903360,"PrivateMemorySize64":238800896,"managedBytes":4050864,"allocatedBytes":22802404296,"gc":[1461,974,974],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38880,"sharedPasses":9720,"driverPasses":9720,"browserPasses":9720}
|
||||
{"cycle":4870,"elapsedSeconds":6462.6500779,"utc":"2026-11-10T19:32:27.7727388Z","WorkingSet64":122109952,"PrivateMemorySize64":243015680,"managedBytes":4125408,"allocatedBytes":22849763944,"gc":[1464,976,976],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":38960,"sharedPasses":9740,"driverPasses":9740,"browserPasses":9740}
|
||||
{"cycle":4880,"elapsedSeconds":6475.8728647,"utc":"2026-11-10T19:32:41.0028163Z","WorkingSet64":119013376,"PrivateMemorySize64":243015680,"managedBytes":4076344,"allocatedBytes":22896968168,"gc":[1467,978,978],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39040,"sharedPasses":9760,"driverPasses":9760,"browserPasses":9760}
|
||||
{"cycle":4890,"elapsedSeconds":6489.4704012,"utc":"2026-11-10T19:32:54.5983217Z","WorkingSet64":119017472,"PrivateMemorySize64":243036160,"managedBytes":4087976,"allocatedBytes":22944237912,"gc":[1470,980,980],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39120,"sharedPasses":9780,"driverPasses":9780,"browserPasses":9780}
|
||||
{"cycle":4900,"elapsedSeconds":6502.6634906,"utc":"2026-11-10T19:33:07.7844883Z","WorkingSet64":119189504,"PrivateMemorySize64":238821376,"managedBytes":4123960,"allocatedBytes":22991398584,"gc":[1473,982,982],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39200,"sharedPasses":9800,"driverPasses":9800,"browserPasses":9800}
|
||||
{"cycle":4910,"elapsedSeconds":6515.9048549,"utc":"2026-11-10T19:33:21.0342868Z","WorkingSet64":118906880,"PrivateMemorySize64":238542848,"managedBytes":4059704,"allocatedBytes":23038551000,"gc":[1476,984,984],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39280,"sharedPasses":9820,"driverPasses":9820,"browserPasses":9820}
|
||||
{"cycle":4920,"elapsedSeconds":6529.1831635,"utc":"2026-11-10T19:33:34.3559789Z","WorkingSet64":118784000,"PrivateMemorySize64":238477312,"managedBytes":3994304,"allocatedBytes":23085855384,"gc":[1479,986,986],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39360,"sharedPasses":9840,"driverPasses":9840,"browserPasses":9840}
|
||||
{"cycle":4930,"elapsedSeconds":6543.17755,"utc":"2026-11-10T19:33:48.3119325Z","WorkingSet64":118775808,"PrivateMemorySize64":238407680,"managedBytes":3928464,"allocatedBytes":23133230928,"gc":[1482,988,988],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39440,"sharedPasses":9860,"driverPasses":9860,"browserPasses":9860}
|
||||
{"cycle":4940,"elapsedSeconds":6556.8265556,"utc":"2026-11-10T19:34:01.9503987Z","WorkingSet64":119091200,"PrivateMemorySize64":238735360,"managedBytes":4007232,"allocatedBytes":23180557088,"gc":[1485,990,990],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39520,"sharedPasses":9880,"driverPasses":9880,"browserPasses":9880}
|
||||
{"cycle":4950,"elapsedSeconds":6570.0225311,"utc":"2026-11-10T19:34:15.1508144Z","WorkingSet64":122916864,"PrivateMemorySize64":242606080,"managedBytes":3921248,"allocatedBytes":23227888456,"gc":[1488,992,992],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39600,"sharedPasses":9900,"driverPasses":9900,"browserPasses":9900}
|
||||
{"cycle":4960,"elapsedSeconds":6583.2502677,"utc":"2026-11-10T19:34:28.3821044Z","WorkingSet64":118792192,"PrivateMemorySize64":238477312,"managedBytes":3994432,"allocatedBytes":23275226456,"gc":[1491,994,994],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39680,"sharedPasses":9920,"driverPasses":9920,"browserPasses":9920}
|
||||
{"cycle":4970,"elapsedSeconds":6596.4421822,"utc":"2026-11-10T19:34:41.5631278Z","WorkingSet64":123322368,"PrivateMemorySize64":243036160,"managedBytes":4130192,"allocatedBytes":23322674512,"gc":[1494,996,996],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39760,"sharedPasses":9940,"driverPasses":9940,"browserPasses":9940}
|
||||
{"cycle":4980,"elapsedSeconds":6609.9071603,"utc":"2026-11-10T19:34:55.0294437Z","WorkingSet64":115003392,"PrivateMemorySize64":238841856,"managedBytes":4130200,"allocatedBytes":23370810824,"gc":[1497,998,998],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39840,"sharedPasses":9960,"driverPasses":9960,"browserPasses":9960}
|
||||
{"cycle":4990,"elapsedSeconds":6623.0875258,"utc":"2026-11-10T19:35:08.246767Z","WorkingSet64":115658752,"PrivateMemorySize64":238546944,"managedBytes":3930520,"allocatedBytes":23417970072,"gc":[1500,1000,1000],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":39920,"sharedPasses":9980,"driverPasses":9980,"browserPasses":9980}
|
||||
{"cycle":5000,"elapsedSeconds":6636.2656837,"utc":"2026-11-10T19:35:21.3871775Z","WorkingSet64":112214016,"PrivateMemorySize64":235089920,"managedBytes":4051936,"allocatedBytes":23465275520,"gc":[1503,1002,1002],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40000,"sharedPasses":10000,"driverPasses":10000,"browserPasses":10000}
|
||||
{"cycle":5010,"elapsedSeconds":6649.4581661,"utc":"2026-11-10T19:35:34.5860256Z","WorkingSet64":118226944,"PrivateMemorySize64":238522368,"managedBytes":4006736,"allocatedBytes":23512544264,"gc":[1506,1004,1004],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40080,"sharedPasses":10020,"driverPasses":10020,"browserPasses":10020}
|
||||
{"cycle":5020,"elapsedSeconds":6662.7255967,"utc":"2026-11-10T19:35:47.8510405Z","WorkingSet64":118534144,"PrivateMemorySize64":238788608,"managedBytes":4112568,"allocatedBytes":23559813432,"gc":[1509,1006,1006],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40160,"sharedPasses":10040,"driverPasses":10040,"browserPasses":10040}
|
||||
{"cycle":5030,"elapsedSeconds":6675.942992,"utc":"2026-11-10T19:36:01.0667856Z","WorkingSet64":118525952,"PrivateMemorySize64":238809088,"managedBytes":4091600,"allocatedBytes":23606996336,"gc":[1512,1008,1008],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40240,"sharedPasses":10060,"driverPasses":10060,"browserPasses":10060}
|
||||
{"cycle":5040,"elapsedSeconds":6689.1504501,"utc":"2026-11-10T19:36:14.2732522Z","WorkingSet64":84996096,"PrivateMemorySize64":243003392,"managedBytes":4051304,"allocatedBytes":23654226640,"gc":[1515,1010,1010],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40320,"sharedPasses":10080,"driverPasses":10080,"browserPasses":10080}
|
||||
{"cycle":5050,"elapsedSeconds":6702.3761049,"utc":"2026-11-10T19:36:27.4978222Z","WorkingSet64":78536704,"PrivateMemorySize64":242667520,"managedBytes":3993856,"allocatedBytes":23701567352,"gc":[1518,1012,1012],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40400,"sharedPasses":10100,"driverPasses":10100,"browserPasses":10100}
|
||||
{"cycle":5060,"elapsedSeconds":6715.5686555,"utc":"2026-11-10T19:36:40.6899593Z","WorkingSet64":74088448,"PrivateMemorySize64":238800896,"managedBytes":4069776,"allocatedBytes":23748836984,"gc":[1521,1014,1014],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40480,"sharedPasses":10120,"driverPasses":10120,"browserPasses":10120}
|
||||
{"cycle":5070,"elapsedSeconds":6729.2253323,"utc":"2026-11-10T19:36:54.3669364Z","WorkingSet64":73740288,"PrivateMemorySize64":238473216,"managedBytes":3992600,"allocatedBytes":23796110264,"gc":[1524,1016,1016],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40560,"sharedPasses":10140,"driverPasses":10140,"browserPasses":10140}
|
||||
{"cycle":5080,"elapsedSeconds":6742.7711569,"utc":"2026-11-10T19:37:07.9108312Z","WorkingSet64":71524352,"PrivateMemorySize64":238473216,"managedBytes":3993256,"allocatedBytes":23843390840,"gc":[1527,1018,1018],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40640,"sharedPasses":10160,"driverPasses":10160,"browserPasses":10160}
|
||||
{"cycle":5090,"elapsedSeconds":6755.9754822,"utc":"2026-11-10T19:37:21.1005986Z","WorkingSet64":80719872,"PrivateMemorySize64":243015680,"managedBytes":4072480,"allocatedBytes":23890872280,"gc":[1530,1020,1020],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40720,"sharedPasses":10180,"driverPasses":10180,"browserPasses":10180}
|
||||
{"cycle":5100,"elapsedSeconds":6769.1815489,"utc":"2026-11-10T19:37:34.3029141Z","WorkingSet64":80785408,"PrivateMemorySize64":243036160,"managedBytes":4072080,"allocatedBytes":23938190040,"gc":[1533,1022,1022],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40800,"sharedPasses":10200,"driverPasses":10200,"browserPasses":10200}
|
||||
{"cycle":5110,"elapsedSeconds":6782.6356772,"utc":"2026-11-10T19:37:47.7594223Z","WorkingSet64":76075008,"PrivateMemorySize64":238473216,"managedBytes":3993192,"allocatedBytes":23985382032,"gc":[1536,1024,1024],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40880,"sharedPasses":10220,"driverPasses":10220,"browserPasses":10220}
|
||||
{"cycle":5120,"elapsedSeconds":6796.0574954,"utc":"2026-11-10T19:38:01.1791795Z","WorkingSet64":76414976,"PrivateMemorySize64":238800896,"managedBytes":4069792,"allocatedBytes":24032761632,"gc":[1539,1026,1026],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":40960,"sharedPasses":10240,"driverPasses":10240,"browserPasses":10240}
|
||||
{"cycle":5130,"elapsedSeconds":6810.0304017,"utc":"2026-11-10T19:38:15.1499803Z","WorkingSet64":80269312,"PrivateMemorySize64":242667520,"managedBytes":3992520,"allocatedBytes":24080041584,"gc":[1542,1028,1028],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41040,"sharedPasses":10260,"driverPasses":10260,"browserPasses":10260}
|
||||
{"cycle":5140,"elapsedSeconds":6823.2193916,"utc":"2026-11-10T19:38:28.3394217Z","WorkingSet64":76140544,"PrivateMemorySize64":238538752,"managedBytes":4059336,"allocatedBytes":24127298840,"gc":[1545,1030,1030],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41120,"sharedPasses":10280,"driverPasses":10280,"browserPasses":10280}
|
||||
{"cycle":5150,"elapsedSeconds":6836.4186724,"utc":"2026-11-10T19:38:41.5397392Z","WorkingSet64":71647232,"PrivateMemorySize64":238563328,"managedBytes":4059656,"allocatedBytes":24174495824,"gc":[1548,1032,1032],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41200,"sharedPasses":10300,"driverPasses":10300,"browserPasses":10300}
|
||||
{"cycle":5160,"elapsedSeconds":6849.8761838,"utc":"2026-11-10T19:38:55.0058003Z","WorkingSet64":71593984,"PrivateMemorySize64":238501888,"managedBytes":4008752,"allocatedBytes":24221822152,"gc":[1551,1034,1034],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41280,"sharedPasses":10320,"driverPasses":10320,"browserPasses":10320}
|
||||
{"cycle":5170,"elapsedSeconds":6863.4352003,"utc":"2026-11-10T19:39:08.5567876Z","WorkingSet64":76111872,"PrivateMemorySize64":243023872,"managedBytes":4064416,"allocatedBytes":24269196400,"gc":[1554,1036,1036],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41360,"sharedPasses":10340,"driverPasses":10340,"browserPasses":10340}
|
||||
{"cycle":5180,"elapsedSeconds":6876.605627,"utc":"2026-11-10T19:39:21.7262022Z","WorkingSet64":72794112,"PrivateMemorySize64":238944256,"managedBytes":4051656,"allocatedBytes":24316529048,"gc":[1557,1038,1038],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41440,"sharedPasses":10360,"driverPasses":10360,"browserPasses":10360}
|
||||
{"cycle":5190,"elapsedSeconds":6889.7919225,"utc":"2026-11-10T19:39:34.9153901Z","WorkingSet64":69259264,"PrivateMemorySize64":235216896,"managedBytes":4124776,"allocatedBytes":24363754176,"gc":[1560,1040,1040],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41520,"sharedPasses":10380,"driverPasses":10380,"browserPasses":10380}
|
||||
{"cycle":5200,"elapsedSeconds":6902.9686972,"utc":"2026-11-10T19:39:48.0926373Z","WorkingSet64":76718080,"PrivateMemorySize64":242667520,"managedBytes":3993496,"allocatedBytes":24411014544,"gc":[1563,1042,1042],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41600,"sharedPasses":10400,"driverPasses":10400,"browserPasses":10400}
|
||||
{"cycle":5210,"elapsedSeconds":6916.28353,"utc":"2026-11-10T19:40:01.4099085Z","WorkingSet64":72908800,"PrivateMemorySize64":238538752,"managedBytes":4059064,"allocatedBytes":24459233824,"gc":[1566,1044,1044],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41680,"sharedPasses":10420,"driverPasses":10420,"browserPasses":10420}
|
||||
{"cycle":5220,"elapsedSeconds":6929.4862049,"utc":"2026-11-10T19:40:14.6077036Z","WorkingSet64":76505088,"PrivateMemorySize64":243015680,"managedBytes":4115936,"allocatedBytes":24506448480,"gc":[1569,1046,1046],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41760,"sharedPasses":10440,"driverPasses":10440,"browserPasses":10440}
|
||||
{"cycle":5230,"elapsedSeconds":6942.686536,"utc":"2026-11-10T19:40:27.8068466Z","WorkingSet64":72048640,"PrivateMemorySize64":238522368,"managedBytes":4007520,"allocatedBytes":24553727008,"gc":[1572,1048,1048],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41840,"sharedPasses":10460,"driverPasses":10460,"browserPasses":10460}
|
||||
{"cycle":5240,"elapsedSeconds":6955.8743857,"utc":"2026-11-10T19:40:40.9986371Z","WorkingSet64":76652544,"PrivateMemorySize64":243044352,"managedBytes":4073744,"allocatedBytes":24600989400,"gc":[1575,1050,1050],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":41920,"sharedPasses":10480,"driverPasses":10480,"browserPasses":10480}
|
||||
{"cycle":5250,"elapsedSeconds":6969.0821747,"utc":"2026-11-10T19:40:54.2132521Z","WorkingSet64":71778304,"PrivateMemorySize64":238518272,"managedBytes":4005784,"allocatedBytes":24648365920,"gc":[1578,1052,1052],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42000,"sharedPasses":10500,"driverPasses":10500,"browserPasses":10500}
|
||||
{"cycle":5260,"elapsedSeconds":6982.2743101,"utc":"2026-11-10T19:41:07.4005649Z","WorkingSet64":76554240,"PrivateMemorySize64":246845440,"managedBytes":3932976,"allocatedBytes":24695635960,"gc":[1581,1054,1054],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42080,"sharedPasses":10520,"driverPasses":10520,"browserPasses":10520}
|
||||
{"cycle":5270,"elapsedSeconds":6995.454983,"utc":"2026-11-10T19:41:20.5750363Z","WorkingSet64":77111296,"PrivateMemorySize64":247332864,"managedBytes":4142304,"allocatedBytes":24743109824,"gc":[1584,1056,1056],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42160,"sharedPasses":10540,"driverPasses":10540,"browserPasses":10540}
|
||||
{"cycle":5280,"elapsedSeconds":7008.6546482,"utc":"2026-11-10T19:41:33.7747507Z","WorkingSet64":72658944,"PrivateMemorySize64":243404800,"managedBytes":4059128,"allocatedBytes":24790220704,"gc":[1587,1058,1058],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42240,"sharedPasses":10560,"driverPasses":10560,"browserPasses":10560}
|
||||
{"cycle":5290,"elapsedSeconds":7022.1668582,"utc":"2026-11-10T19:41:47.3681167Z","WorkingSet64":76464128,"PrivateMemorySize64":247218176,"managedBytes":4134640,"allocatedBytes":24837586664,"gc":[1590,1060,1060],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42320,"sharedPasses":10580,"driverPasses":10580,"browserPasses":10580}
|
||||
{"cycle":5300,"elapsedSeconds":7039.9280885,"utc":"2026-11-10T19:42:05.1661967Z","WorkingSet64":78688256,"PrivateMemorySize64":251043840,"managedBytes":3945384,"allocatedBytes":24884984856,"gc":[1593,1062,1062],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42400,"sharedPasses":10600,"driverPasses":10600,"browserPasses":10600}
|
||||
{"cycle":5310,"elapsedSeconds":7055.1278862,"utc":"2026-11-10T19:42:20.2662731Z","WorkingSet64":80162816,"PrivateMemorySize64":255332352,"managedBytes":3951160,"allocatedBytes":24932626040,"gc":[1596,1064,1064],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42480,"sharedPasses":10620,"driverPasses":10620,"browserPasses":10620}
|
||||
{"cycle":5320,"elapsedSeconds":7069.0184359,"utc":"2026-11-10T19:42:34.139969Z","WorkingSet64":81805312,"PrivateMemorySize64":272982016,"managedBytes":4012896,"allocatedBytes":24980315048,"gc":[1599,1066,1066],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42560,"sharedPasses":10640,"driverPasses":10640,"browserPasses":10640}
|
||||
{"cycle":5330,"elapsedSeconds":7082.4373318,"utc":"2026-11-10T19:42:47.5640317Z","WorkingSet64":80338944,"PrivateMemorySize64":254656512,"managedBytes":4621376,"allocatedBytes":25027699008,"gc":[1602,1068,1068],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42640,"sharedPasses":10660,"driverPasses":10660,"browserPasses":10660}
|
||||
{"cycle":5340,"elapsedSeconds":7095.5659671,"utc":"2026-11-10T19:43:00.6844669Z","WorkingSet64":87146496,"PrivateMemorySize64":261574656,"managedBytes":4762080,"allocatedBytes":25074535664,"gc":[1605,1070,1070],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42720,"sharedPasses":10680,"driverPasses":10680,"browserPasses":10680}
|
||||
{"cycle":5350,"elapsedSeconds":7108.7394385,"utc":"2026-11-10T19:43:13.85707Z","WorkingSet64":87232512,"PrivateMemorySize64":261574656,"managedBytes":4793456,"allocatedBytes":25121278344,"gc":[1608,1072,1072],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42800,"sharedPasses":10700,"driverPasses":10700,"browserPasses":10700}
|
||||
{"cycle":5360,"elapsedSeconds":7121.9721312,"utc":"2026-11-10T19:43:27.0909124Z","WorkingSet64":87257088,"PrivateMemorySize64":261591040,"managedBytes":4138120,"allocatedBytes":25168001184,"gc":[1611,1074,1074],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42880,"sharedPasses":10720,"driverPasses":10720,"browserPasses":10720}
|
||||
{"cycle":5370,"elapsedSeconds":7135.1901751,"utc":"2026-11-10T19:43:40.3089895Z","WorkingSet64":87400448,"PrivateMemorySize64":253333504,"managedBytes":4119904,"allocatedBytes":25215100472,"gc":[1614,1076,1076],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":42960,"sharedPasses":10740,"driverPasses":10740,"browserPasses":10740}
|
||||
{"cycle":5380,"elapsedSeconds":7148.3734604,"utc":"2026-11-10T19:43:53.4910701Z","WorkingSet64":83238912,"PrivateMemorySize64":249159680,"managedBytes":4061016,"allocatedBytes":25262295328,"gc":[1617,1078,1078],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":43040,"sharedPasses":10760,"driverPasses":10760,"browserPasses":10760}
|
||||
{"cycle":5390,"elapsedSeconds":7161.5902538,"utc":"2026-11-10T19:44:06.7080138Z","WorkingSet64":87179264,"PrivateMemorySize64":253087744,"managedBytes":4124728,"allocatedBytes":25309616456,"gc":[1620,1080,1080],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":43120,"sharedPasses":10780,"driverPasses":10780,"browserPasses":10780}
|
||||
{"cycle":5400,"elapsedSeconds":7174.5805733,"utc":"2026-11-10T19:44:19.6989722Z","WorkingSet64":87367680,"PrivateMemorySize64":253272064,"managedBytes":4126184,"allocatedBytes":25356771080,"gc":[1623,1082,1082],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":43200,"sharedPasses":10800,"driverPasses":10800,"browserPasses":10800}
|
||||
{"cycle":5410,"elapsedSeconds":7187.6831487,"utc":"2026-11-10T19:44:32.8064007Z","WorkingSet64":87429120,"PrivateMemorySize64":253272064,"managedBytes":4059880,"allocatedBytes":25403934920,"gc":[1626,1084,1084],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":43280,"sharedPasses":10820,"driverPasses":10820,"browserPasses":10820}
|
||||
{"cycle":5420,"elapsedSeconds":7200.9350359,"utc":"2026-11-10T19:44:46.0522796Z","WorkingSet64":84873216,"PrivateMemorySize64":253251584,"managedBytes":3987480,"allocatedBytes":25451104712,"gc":[1629,1086,1086],"fdCount":148,"ownedRootFdCount":4,"ownedPkiFdCount":0,"survivingProductionObjects":0,"managerDisposalsVerified":43360,"sharedPasses":10840,"driverPasses":10840,"browserPasses":10840}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "Opc.Ua.Core",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "9d0857aa6b7f3c49037d4ea557b4da8edf07e146069464481783e66c5c9cd35a"
|
||||
},
|
||||
{
|
||||
"name": "Opc.Ua.Types",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "c542f69882f4e8a4ebd5ccc28a3881d6967c7ffb6dcc3c56dc6c776f39c2ede1"
|
||||
},
|
||||
{
|
||||
"name": "Opc.Ua.Security.Certificates",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "7f4969aceb2f0db5328c6882cb4b117342f3b18905c38acdba600683860c4fd0"
|
||||
},
|
||||
{
|
||||
"name": "Opc.Ua.Core.Types",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "a7dd141b8dabe8848ff28c2fb8e16a85a0508e6a49e6b1a1c1e267175b99af96"
|
||||
},
|
||||
{
|
||||
"name": "Opc.Ua.Client",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "620da406fabdbc75d11f9827ea7e39d2d3c762471bd2264b0d11f1d6cd9247cd"
|
||||
},
|
||||
{
|
||||
"name": "Opc.Ua.Configuration",
|
||||
"version": "2.0.1.0",
|
||||
"sha256": "6ed6a594c93c3ff35d1a16539a9fe87c1e2640549cc2f48ed6bae333dc8bf0e7"
|
||||
}
|
||||
]
|
||||
@@ -1,149 +0,0 @@
|
||||
{
|
||||
"source": {
|
||||
"commit": "c25561c64d082ea2a42b03791d604f4fe9b72bd9",
|
||||
"durationSeconds": 7200,
|
||||
"mode": "full",
|
||||
"image": {
|
||||
"Id": "sha256:b04611ee9e1b7d36797012ed921962c57189cb4dbb3dff12afb8e158110f293b",
|
||||
"RepoDigests": [
|
||||
"mcr.microsoft.com/dotnet/sdk@sha256:e362a8dbcd691522456da26a5198b8f3ca1d7641c95624fadc5e3e82678bd08a"
|
||||
],
|
||||
"Architecture": "arm64",
|
||||
"Os": "linux"
|
||||
},
|
||||
"network": "none",
|
||||
"startedUtc": "2026-11-10T17:44:32Z",
|
||||
"scope": "actual unchanged production Shared/OpcUaClientDriver/AdminUI browser in a repeated same-process loop; SDK 2.0.1 only"
|
||||
},
|
||||
"containerExitCode": 0,
|
||||
"containerElapsedSeconds": 7204.404327417025,
|
||||
"summary": {
|
||||
"status": "passed",
|
||||
"diagnosticPositiveControl": "exact SDK2 manager false-before/true-after DisposeAsync",
|
||||
"requestedSeconds": 7200,
|
||||
"elapsedSeconds": 7200.984331,
|
||||
"fullTwoHourLifecycle": true,
|
||||
"cycles": 5420,
|
||||
"sharedPasses": 10840,
|
||||
"driverPasses": 10840,
|
||||
"browserPasses": 10840,
|
||||
"managerDisposalsVerified": 43360,
|
||||
"finalResources": {
|
||||
"cycle": 5420,
|
||||
"elapsedSeconds": 7200.9843313,
|
||||
"utc": "2026-11-10T19:44:46.0998573Z",
|
||||
"WorkingSet64": 86102016,
|
||||
"PrivateMemorySize64": 249212928,
|
||||
"managedBytes": 3988520,
|
||||
"allocatedBytes": 25451263856,
|
||||
"gc": [
|
||||
1631,
|
||||
1088,
|
||||
1088
|
||||
],
|
||||
"fdCount": 148,
|
||||
"ownedRootFdCount": 4,
|
||||
"ownedPkiFdCount": 0,
|
||||
"survivingProductionObjects": 0,
|
||||
"managerDisposalsVerified": 43360,
|
||||
"sharedPasses": 10840,
|
||||
"driverPasses": 10840,
|
||||
"browserPasses": 10840
|
||||
},
|
||||
"scope": "Production Shared connect/disconnect/reconnect; production driver Initialize/Reinitialize/Shutdown/dispose; production browser open/browse/dispose; scalar and Int32[3] read/write/subscribe/unsubscribe; strict mutual trusted DER/Basic256Sha256 SignAndEncrypt/API-key fixture. No network stalls, revocation, surgical edits/rebuild, CP abandonment or Windows/AVEVA/performance G4 claim."
|
||||
},
|
||||
"ownCertificatesUnchanged": true,
|
||||
"applicationOwnCertificates": 3,
|
||||
"runtime": "Microsoft.NETCore.App10.0.3 in pinned official Linux ARM64 SDK10.0.103 image; framework-dependent harness",
|
||||
"samples": 543,
|
||||
"first": {
|
||||
"cycle": 0,
|
||||
"elapsedSeconds": 0,
|
||||
"utc": "2026-11-10T17:44:45.1152841Z",
|
||||
"WorkingSet64": 50864128,
|
||||
"PrivateMemorySize64": 87015424,
|
||||
"managedBytes": 243368,
|
||||
"allocatedBytes": 307672,
|
||||
"gc": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
"fdCount": 66,
|
||||
"ownedRootFdCount": 4,
|
||||
"ownedPkiFdCount": 0,
|
||||
"survivingProductionObjects": 0,
|
||||
"managerDisposalsVerified": 0,
|
||||
"sharedPasses": 0,
|
||||
"driverPasses": 0,
|
||||
"browserPasses": 0
|
||||
},
|
||||
"last": {
|
||||
"cycle": 5420,
|
||||
"elapsedSeconds": 7200.9350359,
|
||||
"utc": "2026-11-10T19:44:46.0522796Z",
|
||||
"WorkingSet64": 84873216,
|
||||
"PrivateMemorySize64": 253251584,
|
||||
"managedBytes": 3987480,
|
||||
"allocatedBytes": 25451104712,
|
||||
"gc": [
|
||||
1629,
|
||||
1086,
|
||||
1086
|
||||
],
|
||||
"fdCount": 148,
|
||||
"ownedRootFdCount": 4,
|
||||
"ownedPkiFdCount": 0,
|
||||
"survivingProductionObjects": 0,
|
||||
"managerDisposalsVerified": 43360,
|
||||
"sharedPasses": 10840,
|
||||
"driverPasses": 10840,
|
||||
"browserPasses": 10840
|
||||
},
|
||||
"observedRanges": {
|
||||
"WorkingSet64": {
|
||||
"min": 50864128,
|
||||
"max": 184299520
|
||||
},
|
||||
"PrivateMemorySize64": {
|
||||
"min": 87015424,
|
||||
"max": 272982016
|
||||
},
|
||||
"managedBytes": {
|
||||
"min": 243368,
|
||||
"max": 4793456
|
||||
},
|
||||
"fdCount": {
|
||||
"min": 66,
|
||||
"max": 150
|
||||
},
|
||||
"ownedPkiFdCount": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
},
|
||||
"survivingProductionObjects": {
|
||||
"min": 0,
|
||||
"max": 0
|
||||
}
|
||||
},
|
||||
"evidenceSha256": {
|
||||
"result.json": "9419f70bd292fa9298758b93f8a5e5be7b0d7392060f6b8cdc30a29a6eabe3ad",
|
||||
"source.json": "50a2f15f9059b2a9dd7d738edabbaa13a091f887d3487c4b59616cbad997def0",
|
||||
"task/summary.json": "99d435576c1feba4f1d9439e76d4a4d41d56528e80a778947252a1babcf86d5c",
|
||||
"task/resources.jsonl": "25b367bc7568da44f639f5279640820035bb5cb54611b0108dcb4094cb15ca48",
|
||||
"task/sdk-assemblies.json": "8b4d21b6730efda3f670b41bcdaf480994d4fb68cb19e4cf2705ec105e59a643",
|
||||
"artifact-manifest.json": "595712025561558e2aeaf81a369a66670ddcdbea7e6e9c47329adc7d1a984649",
|
||||
"container-dotnet-info.txt": "671a4199c1703bbae7ae9261df77c03e909b1d903dbf4d68747c9790bba5b03b"
|
||||
},
|
||||
"limits": [
|
||||
"Lifecycle completion and cleanup checks passed; RSS/FD samples are observations, not a baseline-relative performance budget.",
|
||||
"This source predates the unrelated HG1.0 consumer change; no server RSS, history CP churn, revocation, stalls, rebuild, Windows/live or full G4 claim.",
|
||||
"Private PKI, keys and credential-bearing environment remain outside versioned evidence."
|
||||
],
|
||||
"artifactManifest": {
|
||||
"scope": "recursive, all files below immutable app publication",
|
||||
"files": 428,
|
||||
"generatedAfterRun": true,
|
||||
"historicalTopLevelManifestSha256": "456a3fb35d5d5d1b3b141cfe654df3a28a66d5196d362cb6015a125491fd5691"
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
# Issue #799 resolution gates
|
||||
|
||||
Status: prospective procedure under review, **not approved for launch**. The
|
||||
retained cold failures remain failures. This document does not change the plan's
|
||||
resource budgets, establish a replacement baseline, or authorize release.
|
||||
|
||||
## Separate the evidence
|
||||
|
||||
| Question | Evidence required | Current boundary |
|
||||
|---|---|---|
|
||||
| Finite generated-code startup | Fixed canonical operation sequence and bounded, lossless trace windows | Candidate saturation met the selected factory criterion. Summed native MethodSize does not explain all RSS. |
|
||||
| Cross-version lifecycle ownership and memory | Equivalent operations, token invalidation, dropped harness roots, resource-owner checks and matched executable hosts | Original closed objects retain continuation lists while held by the harness; usable steady-state comparison is not established. |
|
||||
| Continuing macOS native retention | Private-key import attribution, bounded native inventory, supported ownership correction and verification | Balanced managed disposal alone has not stopped Apple Security object accumulation. Linux results cannot close this component. |
|
||||
|
||||
The coordinator owns integration and long executions. Two independent Sol agent
|
||||
lanes own `baseline-canonical/` and `native-retention/` respectively; use high
|
||||
effort for control implementation and ownership analysis. Astra at xhigh reviews
|
||||
each control design, its result, any production correction, and the complete
|
||||
acceptance procedure before execution. No worker changes the other lane's files,
|
||||
production factory architecture, immutable baseline, or acceptance denominator.
|
||||
|
||||
## Short controls before a new long run
|
||||
|
||||
The original-SDK lane must demonstrate removal from SessionManager, rejection of
|
||||
the old authentication token, and rejection of old browse/history continuation
|
||||
tokens from a fresh session. A helper boundary must drop all strong Session,
|
||||
continuation and harness references before bounded GC/weak-reference observations.
|
||||
Observe closed-session/point weak references while the same host remains live,
|
||||
then separately observe application/validator/store roots after normal host stop;
|
||||
teardown must not hide retention of closed sessions. Inventory separately
|
||||
identifies which resource owner releases each object.
|
||||
Retain the earlier held-object failure. Do not explicitly dispose abandoned
|
||||
objects or clear caches merely to make the baseline pass. Unsupported original
|
||||
ownership probes remain unsupported, rather than being reported as zero.
|
||||
|
||||
The native lane must attribute configured-store private-key loads separately
|
||||
from public certificate and shared-handle operations using fixed counts and
|
||||
identical certificates. Include a separate bounded store-update semantic control
|
||||
so registry reuse cannot silently bypass configured-store rotation. Review exact
|
||||
SDK 2.0.1 public ownership seams before any
|
||||
application correction. A supported correction needs a failing-before/passing-
|
||||
after ownership control and preserved trust, private-key availability, reconnect
|
||||
and shutdown behavior. Custom crypto, copied transport negotiation, SDK forks,
|
||||
factory substitution and certificate-policy changes require a separate design;
|
||||
they are not fixes authorized by this procedure. Keep private PKI out of Git.
|
||||
|
||||
## Prerequisites for reviewing warmed acceptance
|
||||
|
||||
1. Establish operation/status/order parity and semantically valid close/ownership
|
||||
checks across versions. Match executable host, runtime, architecture and
|
||||
instrumentation. A growing original process is not an accepted denominator.
|
||||
2. Freeze source commits, all artifact hashes, runtime/image identities, private
|
||||
PKI identity, fixtures and the serial same-host schedule before launch.
|
||||
3. Submit the actual harness change, negative controls and immutable artifact
|
||||
receipts to Astra. Approval of diagnostics is not approval of acceptance.
|
||||
4. Resolve continuing macOS native growth independently. A Linux acceptance run
|
||||
cannot waive it, even if the Linux resource guard passes.
|
||||
|
||||
Before this draft becomes executable, define version-appropriate standard-node
|
||||
loading/factory trace coverage for the original binary. The absence of SDK2's
|
||||
`Opc.Ua.OpcUaExtensions` type must not let the original pass an irrelevant zero
|
||||
counter. Also predeclare identical retained-managed/GC and RSS sampling cadence
|
||||
and statistics, including exactly which samples feed the relative 15% comparison.
|
||||
These details remain pending; observed results cannot select them retroactively.
|
||||
|
||||
## Proposed fixed warmup and measurement
|
||||
|
||||
This section is a review proposal only. If the prerequisites and Astra gate pass,
|
||||
qualification uses exactly 384 canonical cycles / 96 restarts plus one settling
|
||||
cycle within 1,800 seconds. The fixed trace windows are cycles 321–352 and
|
||||
353–384, with the continuous veto across their boundary. Require zero generated-
|
||||
factory JIT/load events, zero new SDK assembly loads and zero lost events. Reject
|
||||
missing markers, wrong identity or observer faults. Do not extend or retry the
|
||||
qualification until a favorable sample appears.
|
||||
|
||||
Prospectively select exactly the post-cycle-385 sample as the measurement
|
||||
baseline; do not choose a minimum, median or later sample from observed RSS.
|
||||
Retain all cold, peak and rejected rows. Measurement must then last at least
|
||||
7,200 actual seconds **after** warmup, retaining the +64 MiB managed, +128 MiB
|
||||
RSS and +32 descriptor caps, all canonical operations and semantic/native/
|
||||
ownership guards. Latch the first failure permanently. No resource resets,
|
||||
skipped operations or completion claim on a rejected run.
|
||||
Setup, warmup and final cleanup do not count toward measurement duration. Final
|
||||
shutdown and ownership checks are mandatory after that duration completes.
|
||||
|
||||
For uninstrumented acceptance, first perform an identical fresh paired
|
||||
qualification rehearsal, then use the fixed warmup without EventPipe or
|
||||
allocation StackTrace tracking. The earlier tracked candidate run cannot be
|
||||
relabelled as this evidence. Predefine sampling and statistics for at least three
|
||||
matched representative runs to assess the separate plan-relative throughput,
|
||||
latency, allocation and RSS budgets. A two-hour absolute-cap pass alone does not
|
||||
satisfy those comparisons.
|
||||
|
||||
Only verified results meeting these distinct requirements can support closing
|
||||
#799. Keep #782 G4 and draft PR #802 on hold until their remaining gates also
|
||||
pass; Windows/runtime and licensed interoperability evidence remain separate.
|
||||
@@ -1,144 +0,0 @@
|
||||
using System.Globalization;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Server;
|
||||
using Shouldly;
|
||||
internal static class BaselineMetrics
|
||||
{
|
||||
private static FieldInfo Field(object owner, string name)
|
||||
{
|
||||
for (var type = owner.GetType(); type is not null; type = type.BaseType)
|
||||
if (type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly) is { } member) return member;
|
||||
throw new InvalidOperationException("Missing exact-.182 diagnostic field: " + name);
|
||||
}
|
||||
private static T Required<T>(object owner, string name) => Field(owner, name).GetValue(owner) is T value ? value
|
||||
: throw new InvalidOperationException("Unexpected exact-.182 diagnostic field type: " + name);
|
||||
internal static (int Browse, int History) Points(ISession session)
|
||||
{
|
||||
using (Required<System.Threading.Lock>(session, "m_lock").EnterScope())
|
||||
return (Count(session, "m_browseContinuationPoints"), Count(session, "m_historyContinuationPoints"));
|
||||
}
|
||||
private static int Count(object owner, string name) => Field(owner, name).GetValue(owner) switch
|
||||
{ null => 0, ICollection values => values.Count, _ => throw new InvalidOperationException("Unexpected continuation collection type") };
|
||||
internal static int CachedStoreReferences(CertificateValidator validator)
|
||||
{
|
||||
var gate = Required<SemaphoreSlim>(validator, "m_semaphore");
|
||||
if (!gate.Wait(TimeSpan.FromSeconds(5))) throw new TimeoutException("Original validator diagnostic lock did not settle");
|
||||
try
|
||||
{
|
||||
return new[] { "m_trustedCertificateStore", "m_issuerCertificateStore", "m_rejectedCertificateStore" }
|
||||
.Select(name => Field(validator, name).GetValue(validator))
|
||||
.Count(value => value switch
|
||||
{
|
||||
null => false,
|
||||
CertificateStoreIdentifier store => Field(store, "m_store").GetValue(store) switch
|
||||
{ null => false, ICertificateStore => true, _ => throw new InvalidOperationException("Original cached store type changed") },
|
||||
_ => throw new InvalidOperationException("Original validator store identifier type changed")
|
||||
});
|
||||
}
|
||||
finally { gate.Release(); }
|
||||
}
|
||||
internal static int Counter(object manager, string name)
|
||||
{
|
||||
var property = manager.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("Missing original node-manager diagnostic property: " + name);
|
||||
return property.PropertyType == typeof(int) && property.GetValue(manager) is int value ? value
|
||||
: throw new InvalidOperationException("Unexpected original node-manager diagnostic property type: " + name);
|
||||
}
|
||||
internal static async Task<(int Total, int Pki)> DescriptorsAsync(CancellationToken ct, params string[] roots)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
var canonicalRoots = roots.Select(root => CanonicalPath(root)).Distinct(StringComparer.Ordinal).ToArray();
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
var targets = Directory.EnumerateFileSystemEntries("/proc/self/fd")
|
||||
.Select(path => new FileInfo(path).LinkTarget).ToArray();
|
||||
return (targets.Length, targets.Count(path => IsWithinRoots(path, canonicalRoots)));
|
||||
}
|
||||
if (OperatingSystem.IsMacOS())
|
||||
{
|
||||
using var process = new Process { StartInfo = new ProcessStartInfo("/usr/sbin/lsof")
|
||||
{ RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false } };
|
||||
foreach (var arg in new[] { "-a", "-p", Environment.ProcessId.ToString(CultureInfo.InvariantCulture), "-Fnf" })
|
||||
process.StartInfo.ArgumentList.Add(arg);
|
||||
var text = await ReadDescriptorProbeAsync(process, TimeSpan.FromSeconds(5), ct);
|
||||
process.ExitCode.ShouldBe(0);
|
||||
var total = 0;
|
||||
var pki = 0;
|
||||
var descriptor = false;
|
||||
foreach (var line in text.Split('\n'))
|
||||
{
|
||||
if (line.StartsWith('f'))
|
||||
{
|
||||
descriptor = line.Length > 1 && char.IsDigit(line[1]);
|
||||
if (descriptor) total++;
|
||||
}
|
||||
else if (descriptor && line.StartsWith('n') && IsWithinRoots(line[1..], canonicalRoots)) pki++;
|
||||
}
|
||||
return (total, pki);
|
||||
}
|
||||
throw new PlatformNotSupportedException("This soak requires Linux procfs or macOS lsof for actual descriptor evidence.");
|
||||
}
|
||||
|
||||
private static async Task<string> ReadDescriptorProbeAsync(Process process, TimeSpan timeout, CancellationToken ct)
|
||||
{
|
||||
using var deadline = CancellationTokenSource.CreateLinkedTokenSource(ct);
|
||||
deadline.CancelAfter(timeout);
|
||||
process.Start();
|
||||
var stdout = process.StandardOutput.ReadToEndAsync(deadline.Token);
|
||||
var stderr = process.StandardError.ReadToEndAsync(deadline.Token);
|
||||
var exited = process.WaitForExitAsync(deadline.Token);
|
||||
try
|
||||
{
|
||||
// Waiting for exit alone does not bound reads: both redirected pipes must also finish.
|
||||
await Task.WhenAll(stdout, stderr, exited).WaitAsync(deadline.Token).ConfigureAwait(false);
|
||||
return await stdout.ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
try { if (!process.HasExited) process.Kill(entireProcessTree: true); }
|
||||
catch (InvalidOperationException) when (process.HasExited) { /* It exited between the check and kill. */ }
|
||||
await process.WaitForExitAsync(CancellationToken.None).WaitAsync(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
|
||||
// Observe both cancelled drains; never leave a pipe read running after returning.
|
||||
try { await Task.WhenAll(stdout, stderr).WaitAsync(TimeSpan.FromSeconds(2)).ConfigureAwait(false); }
|
||||
catch (OperationCanceledException) { }
|
||||
if (ct.IsCancellationRequested) throw;
|
||||
throw new TimeoutException("Descriptor probe exceeded its process and redirected-stream deadline.");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsWithinRoots(string? path, IReadOnlyList<string> roots)
|
||||
{
|
||||
if (path is null || !Path.IsPathFullyQualified(path)) return false;
|
||||
// procfs marks an unlinked but still open file; its containing physical directory still counts.
|
||||
const string deleted = " (deleted)";
|
||||
if (path.EndsWith(deleted, StringComparison.Ordinal)) path = path[..^deleted.Length];
|
||||
var canonical = CanonicalPath(path);
|
||||
return roots.Any(root => canonical.Equals(root, StringComparison.Ordinal)
|
||||
|| canonical.StartsWith(Path.EndsInDirectorySeparator(root) ? root : root + Path.DirectorySeparatorChar,
|
||||
StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
private static string CanonicalPath(string path, int depth = 0)
|
||||
{
|
||||
if (depth > 32) throw new IOException("Descriptor path link resolution exceeded its bound.");
|
||||
var full = Path.GetFullPath(path);
|
||||
var current = Path.GetPathRoot(full)!;
|
||||
foreach (var component in full[current.Length..].Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
current = Path.Combine(current, component);
|
||||
FileSystemInfo entry = Directory.Exists(current) ? new DirectoryInfo(current) : new FileInfo(current);
|
||||
if (entry.LinkTarget is not null)
|
||||
{
|
||||
var target = entry.ResolveLinkTarget(returnFinalTarget: true)
|
||||
?? throw new IOException("Descriptor path link resolution returned no target.");
|
||||
// Resolve parent links too: an alias target can itself begin with /var or /tmp.
|
||||
current = CanonicalPath(target.FullName, depth + 1);
|
||||
}
|
||||
}
|
||||
return Path.TrimEndingDirectorySeparator(current);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Opc.Ua;
|
||||
using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Authorization;
|
||||
using ZB.MOM.WW.OtOpcUa.OpcUaServer;
|
||||
using ZB.MOM.WW.OtOpcUa.OpcUaServer.Security;
|
||||
|
||||
internal sealed class BaselineRig : IAsyncDisposable
|
||||
{
|
||||
internal const string Cluster = "SITE-A", RawDeviceFolder = "Plant/Modbus/dev1", RawAlarmPath = "Plant/Modbus/dev1/temp_hi";
|
||||
internal const string EqA = "EqA", EqB = "EqB", KeyPrincipal = "event-probe", KeyId = "k-server-events";
|
||||
internal static string KeyPassword => Environment.GetEnvironmentVariable("OTOPCUA_BASELINE_CANONICAL_KEY")
|
||||
?? throw new InvalidOperationException("An ephemeral fixture credential is required");
|
||||
private readonly OpcUaApplicationHostOptions _options;
|
||||
private OpcUaApplicationHost _host = null!;
|
||||
private bool _disposed;
|
||||
internal OtOpcUaSdkServer Server { get; private set; } = null!;
|
||||
internal OtOpcUaNodeManager Nm => Server.NodeManager!;
|
||||
internal SdkAddressSpaceSink Sink { get; private set; } = null!;
|
||||
internal string EndpointUrl => $"opc.tcp://127.0.0.1:{_options.OpcUaPort}/OtOpcUa";
|
||||
internal string PkiRoot { get; }
|
||||
internal CertificateValidator Validator
|
||||
{
|
||||
get
|
||||
{
|
||||
var applicationField = typeof(OpcUaApplicationHost).GetField("_application", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
?? throw new InvalidOperationException("Original host application field is missing");
|
||||
return applicationField.GetValue(_host) is Opc.Ua.Configuration.ApplicationInstance application
|
||||
&& application.ApplicationConfiguration.CertificateValidator is CertificateValidator validator ? validator
|
||||
: throw new InvalidOperationException("Original host application field type changed");
|
||||
}
|
||||
}
|
||||
internal BaselineRig(string directory)
|
||||
{
|
||||
PkiRoot = Path.Combine(directory, "server-pki");
|
||||
using var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
_options = new OpcUaApplicationHostOptions
|
||||
{
|
||||
ApplicationName = "OtOpcUa.SDK2LifecycleSoak", ApplicationUri = $"urn:OtOpcUa.SDK2LifecycleSoak.{Guid.NewGuid():N}",
|
||||
OpcUaPort = ((IPEndPoint)listener.LocalEndpoint).Port, PublicHostname = "127.0.0.1", PkiStoreRoot = PkiRoot,
|
||||
EnabledSecurityProfiles = [OpcUaSecurityProfile.None, OpcUaSecurityProfile.Basic256Sha256SignAndEncrypt],
|
||||
AutoAcceptUntrustedClientCertificates = true,
|
||||
};
|
||||
}
|
||||
internal async Task BootAsync(CancellationToken ct)
|
||||
{
|
||||
Server = new OtOpcUaSdkServer();
|
||||
_host = new OpcUaApplicationHost(_options, NullLogger<OpcUaApplicationHost>.Instance, new Auth());
|
||||
await _host.StartAsync(Server, ct);
|
||||
Canonical.Ledger.Record("host-start");
|
||||
Sink = new SdkAddressSpaceSink(Nm);
|
||||
}
|
||||
internal async Task RestartAsync(CancellationToken ct)
|
||||
{
|
||||
await _host.DisposeAsync();
|
||||
Canonical.Ledger.Record("host-stop");
|
||||
await BootAsync(ct);
|
||||
}
|
||||
internal DataPlaneAuthorityState Enforce(bool enabled, ApiKey[] keys, params NodeAcl[] grants)
|
||||
{
|
||||
var state = new DataPlaneAuthorityState();
|
||||
state.Apply(Cluster, "rev-1", keys, grants, new Dictionary<AclScopeRef, IReadOnlyList<NodeAclPath>>
|
||||
{
|
||||
[new AclScopeRef(NodeAclScopeKind.Equipment, "eq-" + EqA)] = [new NodeAclPath([NodeAclRealms.Uns, EqA])],
|
||||
[new AclScopeRef(NodeAclScopeKind.Equipment, "eq-" + EqB)] = [new NodeAclPath([NodeAclRealms.Uns, EqB])]
|
||||
});
|
||||
Nm.DataPlaneAuthority = state;
|
||||
Nm.Authorizer = new DataPlaneAuthorizer(state, new TriePermissionEvaluator(state.Tries), enabled, NullLogger.Instance, TimeProvider.System);
|
||||
Canonical.Ledger.Record("authority-restore");
|
||||
return state;
|
||||
}
|
||||
internal static ApiKey Key() => new() { ApiKeyId = KeyId, Name = KeyId, SecretHash = "hash", Principal = KeyPrincipal,
|
||||
Enabled = true, CreatedUtc = DateTime.UtcNow.AddDays(-1) };
|
||||
internal static NodeAcl ClusterGrant(string principal, string id, NodePermissions permissions) => new()
|
||||
{ NodeAclId = id, ClusterId = Cluster, Principal = principal, ScopeKind = NodeAclScopeKind.Cluster, PermissionFlags = permissions };
|
||||
internal void MaterialiseNative()
|
||||
{
|
||||
Sink.EnsureFolder(RawDeviceFolder, null, "dev1", AddressSpaceRealm.Raw);
|
||||
Sink.MaterialiseAlarmCondition(RawAlarmPath, RawDeviceFolder, "temp_hi", "OffNormalAlarm", 700, AddressSpaceRealm.Raw, isNative: true);
|
||||
Sink.EnsureFolder(EqA, null, "A", AddressSpaceRealm.Uns);
|
||||
Sink.EnsureFolder(EqB, null, "B", AddressSpaceRealm.Uns);
|
||||
Sink.WireAlarmNotifiers(RawAlarmPath, AddressSpaceRealm.Raw, [EqA, EqB], AddressSpaceRealm.Uns);
|
||||
}
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
try
|
||||
{
|
||||
if (_host is not null) { await _host.DisposeAsync(); Canonical.Ledger.Record("host-stop"); }
|
||||
}
|
||||
finally { if (Directory.Exists(PkiRoot)) Directory.Delete(PkiRoot, true); }
|
||||
}
|
||||
private sealed class Auth : IOpcUaUserAuthenticator
|
||||
{
|
||||
public Task<OpcUaUserAuthResult> AuthenticateUserNameAsync(string username, string password, CancellationToken ct) =>
|
||||
Task.FromResult(username == "apikey" && password.StartsWith($"otua_{KeyId}_", StringComparison.Ordinal)
|
||||
? OpcUaUserAuthResult.AllowKey(KeyPrincipal, [OpcUaDataPlaneRoles.AlarmAck, OpcUaDataPlaneRoles.WriteOperate], KeyId)
|
||||
: OpcUaUserAuthResult.Deny("Invalid fixture key"));
|
||||
}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Opc.Ua.Configuration;
|
||||
using Shouldly;
|
||||
using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Authorization;
|
||||
using ClientSession = Opc.Ua.Client.ISession;
|
||||
using Subscription = Opc.Ua.Client.Subscription;
|
||||
using MonitoredItem = Opc.Ua.Client.MonitoredItem;
|
||||
internal static partial class Canonical
|
||||
{
|
||||
private static void Configure(BaselineRig rig)
|
||||
{
|
||||
Ledger.Record("configure");
|
||||
rig.MaterialiseNative();
|
||||
rig.Nm.HistorianDataSource = new SqlLikeEventSource(Enumerable.Range(0, 40)
|
||||
.Select(i => new HistoricalEvent($"soak-{i}", "source", Epoch.AddSeconds(i), Epoch, "soak", 500)).ToList());
|
||||
rig.Nm.NodeWriteGateway = new AcceptWrites();
|
||||
MaterialiseValues(rig);
|
||||
rig.Enforce(true, [BaselineRig.Key()], Grant());
|
||||
}
|
||||
|
||||
private static ZB.MOM.WW.OtOpcUa.Configuration.Entities.NodeAcl Grant() => BaselineRig.ClusterGrant(
|
||||
BaselineRig.KeyPrincipal, "soak-grant", NodePermissions.Browse | NodePermissions.Read | NodePermissions.Subscribe
|
||||
| NodePermissions.WriteOperate | NodePermissions.HistoryRead);
|
||||
|
||||
private static void MaterialiseValues(BaselineRig rig)
|
||||
{
|
||||
rig.Sink.EnsureFolder(BaselineRig.RawDeviceFolder, null, "Device", AddressSpaceRealm.Raw);
|
||||
rig.Sink.EnsureVariable(Scalar, BaselineRig.RawDeviceFolder, "Scalar", "Int32", true, AddressSpaceRealm.Raw);
|
||||
rig.Sink.EnsureVariable(ArrayTag, BaselineRig.RawDeviceFolder, "Array", "Int16", true, AddressSpaceRealm.Raw,
|
||||
isArray: true, arrayLength: 4);
|
||||
rig.Sink.EnsureFolder("SoakEquipment", null, "Equipment", AddressSpaceRealm.Uns);
|
||||
rig.Sink.EnsureVariable(UnsScalar, "SoakEquipment", "Scalar", "Int32", true, AddressSpaceRealm.Uns);
|
||||
for (var i = 0; i < 16; i++) rig.Sink.EnsureVariable($"{BaselineRig.RawDeviceFolder}/Browse{i}",
|
||||
BaselineRig.RawDeviceFolder, $"Browse{i}", "Int32", false, AddressSpaceRealm.Raw);
|
||||
rig.Sink.WriteValue(Scalar, 0, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
rig.Sink.WriteValue(ArrayTag, new short[] { 0, 1, 2, 3 }, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
rig.Sink.WriteValue(UnsScalar, 0, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Uns);
|
||||
}
|
||||
|
||||
private static async Task ExerciseAsync(BaselineRig rig, ApplicationConfiguration config, int cycle,
|
||||
StreamWriter evidence, CancellationToken ct)
|
||||
{
|
||||
await using var proxy = new PauseProxy(new Uri(rig.EndpointUrl).Port);
|
||||
using var owner = await ConnectAsync(rig, config, proxy.Port, ct);
|
||||
using var other = await ConnectAsync(rig, config, null, ct);
|
||||
var ownedSessions = rig.Server.CurrentInstance.SessionManager.GetSessions().ToArray();
|
||||
ownedSessions.Length.ShouldBe(2);
|
||||
var scalar = Raw(owner, Scalar);
|
||||
var array = Raw(owner, ArrayTag);
|
||||
var unsNs = owner.NamespaceUris.GetIndex(V3NodeIds.UnsNamespaceUri);
|
||||
unsNs.ShouldBeGreaterThan(0);
|
||||
var uns = new NodeId(UnsScalar, (ushort)unsNs);
|
||||
owner.NamespaceUris.GetString(scalar.NamespaceIndex).ShouldBe(V3NodeIds.RawNamespaceUri);
|
||||
owner.NamespaceUris.GetString(uns.NamespaceIndex).ShouldBe(V3NodeIds.UnsNamespaceUri);
|
||||
using var subscription = new Subscription(owner.DefaultSubscription) { PublishingInterval = 100, KeepAliveCount = 10 };
|
||||
owner.AddSubscription(subscription);
|
||||
try
|
||||
{
|
||||
await Ledger.Call("subscription-create", () => subscription.CreateAsync(ct));
|
||||
var seen = new ConcurrentDictionary<NodeId, Variant>();
|
||||
foreach (var id in new[] { scalar, array, uns })
|
||||
{
|
||||
var item = new MonitoredItem(subscription.DefaultItem) { StartNodeId = id, AttributeId = Attributes.Value,
|
||||
SamplingInterval = 50, QueueSize = 10 };
|
||||
item.Notification += (sender, _) =>
|
||||
{
|
||||
foreach (var value in sender.DequeueValues()) if (StatusCode.IsGood(value.StatusCode)) seen[id] = value.WrappedValue;
|
||||
};
|
||||
subscription.AddItem(item);
|
||||
}
|
||||
await Ledger.Call("subscription-apply", () => subscription.ApplyChangesAsync(ct));
|
||||
subscription.MonitoredItems.ShouldAllBe(item => ServiceResult.IsGood(item.Status.Error));
|
||||
PublicCounts(rig).ShouldBe((2, 1, 3));
|
||||
var values = new short[] { (short)(cycle % 30000), 2, 3, 4 };
|
||||
var writes = await Ledger.Call("write", () => owner.WriteAsync(null, new[]
|
||||
{
|
||||
new WriteValue { NodeId = scalar, AttributeId = Attributes.Value, Value = new DataValue(new Variant(cycle)) },
|
||||
new WriteValue { NodeId = array, AttributeId = Attributes.Value, Value = new DataValue(new Variant(values)) },
|
||||
new WriteValue { NodeId = uns, AttributeId = Attributes.Value, Value = new DataValue(new Variant(cycle)) },
|
||||
}, ct));
|
||||
writes.Results.ToList().ShouldAllBe(status => status == StatusCodes.Good);
|
||||
(await Ledger.Call("read-value", () => owner.ReadValueAsync(scalar, ct))).Value.ShouldBeOfType<int>().ShouldBe(cycle);
|
||||
(await Ledger.Call("read-value", () => owner.ReadValueAsync(array, ct))).Value.ShouldBeOfType<short[]>().ShouldBe(values);
|
||||
(await Ledger.Call("read-value", () => owner.ReadValueAsync(uns, ct))).Value.ShouldBeOfType<int>().ShouldBe(cycle);
|
||||
await EventuallyAsync(() => seen.TryGetValue(scalar, out var value) && ScalarValue(value) == cycle
|
||||
&& seen.ContainsKey(array) && seen.TryGetValue(uns, out var mirror) && ScalarValue(mirror) == cycle, ct);
|
||||
|
||||
// One explicitly released and one deliberately abandoned browse point.
|
||||
var browse = await BrowseAsync(owner, ct);
|
||||
RequirePoint(browse);
|
||||
(await Ledger.Call("browse-next", () => owner.BrowseNextAsync(null, true, [browse], ct))).Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
RequirePoint(await BrowseAsync(owner, ct));
|
||||
// Production history points: cross-session denial, single-use resume, explicit release and close cleanup.
|
||||
var first = (await PageAsync(owner, default, false, ct)).ContinuationPoint;
|
||||
RequirePoint(first);
|
||||
(await PageAsync(other, first, false, ct)).StatusCode.ShouldBe(StatusCodes.BadContinuationPointInvalid);
|
||||
var next = (await PageAsync(owner, first, false, ct)).ContinuationPoint;
|
||||
RequirePoint(next);
|
||||
(await PageAsync(owner, next, true, ct)).StatusCode.ShouldBe(StatusCodes.Good);
|
||||
for (var i = 0; i < 6; i++) RequirePoint((await PageAsync(owner, default, false, ct)).ContinuationPoint);
|
||||
var held = ownedSessions.Select(ContinuationCounts).ToArray();
|
||||
held.Sum(count => count.Browse).ShouldBeGreaterThan(0);
|
||||
held.Sum(count => count.History).ShouldBeGreaterThan(0);
|
||||
var active = PublicCounts(rig);
|
||||
await LogAsync(evidence, new { kind = "active", cycle, sessions = active.Sessions,
|
||||
subscriptions = active.Subscriptions, items = active.Items, browsePoints = held.Sum(x => x.Browse), historyPoints = held.Sum(x => x.History) });
|
||||
|
||||
rig.Nm.UpdateTagAttributes(Scalar, false, null, "Int32", false, null, AddressSpaceRealm.Raw).ShouldBeTrue();
|
||||
Ledger.Record("writable-off");
|
||||
rig.Nm.UpdateTagAttributes(Scalar, true, null, "Int32", false, null, AddressSpaceRealm.Raw).ShouldBeTrue();
|
||||
Ledger.Record("writable-on");
|
||||
rig.Nm.RemoveVariableNode(ArrayTag, AddressSpaceRealm.Raw).ShouldBeTrue();
|
||||
Ledger.Record("variable-remove");
|
||||
rig.Sink.EnsureVariable(ArrayTag, BaselineRig.RawDeviceFolder, "Array", "Int16", true, AddressSpaceRealm.Raw,
|
||||
isArray: true, arrayLength: 4);
|
||||
rig.Sink.WriteValue(ArrayTag, values, OpcUaStatus.Good, DateTime.UtcNow, AddressSpaceRealm.Raw);
|
||||
var authority = rig.Nm.DataPlaneAuthority.ShouldBeOfType<DataPlaneAuthorityState>();
|
||||
Ledger.Record("key-revoke");
|
||||
authority.Apply(BaselineRig.Cluster, $"revoked-{cycle}", [], [Grant()],
|
||||
new Dictionary<AclScopeRef, IReadOnlyList<NodeAclPath>>());
|
||||
var denied = await Ledger.Call("read-service", () => owner.ReadAsync(null, 0, TimestampsToReturn.Neither,
|
||||
[new ReadValueId { NodeId = scalar, AttributeId = Attributes.Value }], ct));
|
||||
denied.Results[0].StatusCode.ShouldBe(StatusCodes.BadUserAccessDenied);
|
||||
rig.Enforce(true, [BaselineRig.Key()], Grant());
|
||||
|
||||
proxy.Pause();
|
||||
Ledger.Record("network-pause");
|
||||
var stalled = Stopwatch.StartNew();
|
||||
string stalledStatus;
|
||||
try
|
||||
{
|
||||
using var timeout = CancellationTokenSource.CreateLinkedTokenSource(ct);
|
||||
timeout.CancelAfter(TimeSpan.FromSeconds(1));
|
||||
await Ledger.Call("read-value", () => owner.ReadValueAsync(scalar, timeout.Token)).WaitAsync(TimeSpan.FromSeconds(5), ct);
|
||||
throw new InvalidOperationException("The deliberately paused network unexpectedly completed the read.");
|
||||
}
|
||||
catch (OperationCanceledException) when (!ct.IsCancellationRequested) { stalledStatus = "OperationCanceled"; }
|
||||
// Exact-tag ChannelAsyncOperation maps a canceled completion waiter to BadRequestInterrupted.
|
||||
catch (ServiceResultException error) when (error.StatusCode == StatusCodes.BadTimeout
|
||||
|| error.StatusCode == StatusCodes.BadRequestCancelledByClient || error.StatusCode == StatusCodes.BadRequestTimeout
|
||||
|| error.StatusCode == StatusCodes.BadRequestInterrupted) { stalledStatus = error.StatusCode.ToString(); }
|
||||
finally { proxy.Resume(); }
|
||||
(await Ledger.Call("read-value", () => owner.ReadValueAsync(scalar, ct))).StatusCode.ShouldBe(StatusCodes.Good);
|
||||
await LogAsync(evidence, new { kind = "network-stall-recovered", cycle, status = stalledStatus, seconds = stalled.Elapsed.TotalSeconds });
|
||||
await Ledger.Call("subscription-delete", () => subscription.DeleteAsync(true, ct));
|
||||
await Ledger.Call("subscription-remove", () => owner.RemoveSubscriptionAsync(subscription, ct));
|
||||
rig.Sink.RebuildAddressSpace();
|
||||
Ledger.Record("address-space-rebuild");
|
||||
Configure(rig);
|
||||
Ledger.Record("cycle-wire-body-completed");
|
||||
}
|
||||
finally
|
||||
{
|
||||
proxy.Resume();
|
||||
await Ledger.Call("session-close", () => owner.CloseAsync(ct)).WaitAsync(TimeSpan.FromSeconds(10), ct);
|
||||
await Ledger.Call("session-close", () => other.CloseAsync(ct)).WaitAsync(TimeSpan.FromSeconds(10), ct);
|
||||
foreach (var closed in ownedSessions)
|
||||
{
|
||||
var before = ContinuationCounts(closed);
|
||||
if (before != (0, 0))
|
||||
{
|
||||
await LogAsync(evidence, new { kind = "closed-session-observation", cycle,
|
||||
activeSessions = rig.Server.CurrentInstance.SessionManager.GetSessions().Count,
|
||||
browsePoints = before.Browse, historyPoints = before.History, diagnosticReferenceHeld = true });
|
||||
await Task.Delay(250, ct); // Read-only failure investigation; never turns the failed guard into a pass.
|
||||
var after = ContinuationCounts(closed);
|
||||
await LogAsync(evidence, new { kind = "closed-session-after-fixed-observation", cycle,
|
||||
observationMilliseconds = 250, browsePoints = after.Browse, historyPoints = after.History });
|
||||
}
|
||||
before.ShouldBe((0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task RestartWithActiveResourcesAsync(BaselineRig rig, ApplicationConfiguration config,
|
||||
CancellationToken ct)
|
||||
{
|
||||
using var client = await ConnectAsync(rig, config, null, ct);
|
||||
using var subscription = new Subscription(client.DefaultSubscription) { PublishingInterval = 100 };
|
||||
client.AddSubscription(subscription);
|
||||
await Ledger.Call("subscription-create", () => subscription.CreateAsync(ct));
|
||||
subscription.AddItem(new MonitoredItem(subscription.DefaultItem)
|
||||
{
|
||||
StartNodeId = Raw(client, Scalar), AttributeId = Attributes.Value, SamplingInterval = 50,
|
||||
});
|
||||
await Ledger.Call("subscription-apply", () => subscription.ApplyChangesAsync(ct));
|
||||
PublicCounts(rig).ShouldBe((1, 1, 1));
|
||||
RequirePoint(await BrowseAsync(client, ct));
|
||||
RequirePoint((await PageAsync(client, default, false, ct)).ContinuationPoint);
|
||||
var oldInternal = rig.Server.CurrentInstance;
|
||||
var oldSessionManager = oldInternal.SessionManager;
|
||||
var oldSubscriptionManager = oldInternal.SubscriptionManager;
|
||||
var oldSessions = oldSessionManager.GetSessions().ToArray();
|
||||
var oldSubscriptions = oldSubscriptionManager.GetSubscriptions().ToArray();
|
||||
var oldValidator = rig.Validator;
|
||||
var oldStores = BaselineMetrics.CachedStoreReferences(oldValidator);
|
||||
await rig.RestartAsync(ct).WaitAsync(TimeSpan.FromSeconds(20), ct);
|
||||
oldSessionManager.GetSessions().ShouldBeEmpty();
|
||||
oldSubscriptionManager.GetSubscriptions().ShouldBeEmpty();
|
||||
oldSubscriptions.ShouldAllBe(item => item.MonitoredItemCount == 0);
|
||||
foreach (var session in oldSessions) ContinuationCounts(session).ShouldBe((0, 0));
|
||||
await LogAsync(CurrentEvidence, new { kind = "original-validator-after-stop", cachedStoreReferencesBefore = oldStores,
|
||||
cachedStoreReferencesAfter = BaselineMetrics.CachedStoreReferences(oldValidator),
|
||||
disposalFlagObservable = false, reason = "SDK1.5 has no CertificateManager disposal API or disposed flag" });
|
||||
PublicCounts(rig).ShouldBe((0, 0, 0));
|
||||
}
|
||||
|
||||
private static async Task<ClientSession> ConnectAsync(BaselineRig rig, ApplicationConfiguration config,
|
||||
int? proxyPort, CancellationToken ct)
|
||||
{
|
||||
var telemetry = DefaultTelemetry.Create(_ => { });
|
||||
var endpoint = await CoreClientUtils.SelectEndpointAsync(config, rig.EndpointUrl, true, telemetry, ct)
|
||||
?? throw new InvalidOperationException("No encrypted endpoint.");
|
||||
endpoint.SecurityMode.ShouldBe(MessageSecurityMode.SignAndEncrypt);
|
||||
if (proxyPort is { } port) endpoint.EndpointUrl = $"opc.tcp://127.0.0.1:{port}/OtOpcUa";
|
||||
return await Ledger.Call("session-create", () => new DefaultSessionFactory(telemetry).CreateAsync(config,
|
||||
new ConfiguredEndpoint(null, endpoint, EndpointConfiguration.Create(config)), false, false,
|
||||
"SDK2LifecycleSoak", 15_000, new UserIdentity("apikey", Encoding.UTF8.GetBytes(BaselineRig.KeyPassword)), default, ct));
|
||||
}
|
||||
|
||||
private static NodeId Raw(ClientSession session, string id)
|
||||
{
|
||||
var ns = session.NamespaceUris.GetIndex(V3NodeIds.RawNamespaceUri);
|
||||
ns.ShouldBeGreaterThan(0);
|
||||
return new NodeId(id, (ushort)ns);
|
||||
}
|
||||
|
||||
private static async Task<byte[]?> BrowseAsync(ClientSession session, CancellationToken ct) =>
|
||||
(await Ledger.Call("browse", () => session.BrowseAsync(null, null, 1, [new BrowseDescription
|
||||
{
|
||||
NodeId = Raw(session, BaselineRig.RawDeviceFolder), BrowseDirection = BrowseDirection.Forward,
|
||||
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true,
|
||||
ResultMask = (uint)BrowseResultMask.All,
|
||||
}], ct))).Results[0].ContinuationPoint;
|
||||
|
||||
private static async Task<Opc.Ua.HistoryReadResult> PageAsync(ClientSession session, byte[]? point,
|
||||
bool release, CancellationToken ct) => (await Ledger.Call("history-read", () => session.HistoryReadAsync(null, new ExtensionObject(new ReadEventDetails
|
||||
{
|
||||
StartTime = Epoch.AddDays(-1), EndTime = Epoch.AddDays(1), NumValuesPerNode = 4,
|
||||
Filter = new EventFilter { SelectClauses = [new SimpleAttributeOperand(ObjectTypeIds.BaseEventType,
|
||||
new QualifiedName(BrowseNames.EventId))] },
|
||||
}), TimestampsToReturn.Both, release,
|
||||
[new HistoryReadValueId { NodeId = Raw(session, BaselineRig.RawDeviceFolder), ContinuationPoint = point }], ct))).Results[0];
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Server;
|
||||
using ZB.MOM.WW.OtOpcUa.OpcUaServer;
|
||||
var types = new[] { typeof(Session), typeof(CertificateValidator), typeof(CertificateStoreIdentifier),
|
||||
typeof(Opc.Ua.Configuration.ApplicationInstance), typeof(OtOpcUaSdkServer), typeof(OpcUaApplicationHost), typeof(OtOpcUaNodeManager) };
|
||||
Console.WriteLine(JsonSerializer.Serialize(new
|
||||
{
|
||||
sdk = typeof(NodeId).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion,
|
||||
sdkFile = FileVersionInfo.GetVersionInfo(typeof(NodeId).Assembly.Location).FileVersion,
|
||||
modules = types.Select(t => new { type = t.FullName, assembly = t.Assembly.GetName().Name, mvid = t.Module.ModuleVersionId,
|
||||
interfaces = t.GetInterfaces().Select(x => x.FullName),
|
||||
fields = t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)
|
||||
.Select(f => new { name = f.Name, type = f.FieldType.FullName }),
|
||||
lifecycle = t.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.Contains("Dispose") || m.Name.Contains("Close") || m.Name.Contains("Stop"))
|
||||
.Select(m => m.ToString()) })
|
||||
}, new JsonSerializerOptions { WriteIndented = true }));
|
||||
@@ -1,167 +0,0 @@
|
||||
# Original close semantics and bounded retention controls
|
||||
|
||||
These are separately reviewed short controls against the unchanged 83ed880e
|
||||
publication, SDK 1.5.378.182. They do not replace the historical `(1 browse,
|
||||
6 history)` held-list port comparison, change an oracle, approve a memory
|
||||
baseline, or claim an unbounded leak. The operation deadline is 120 seconds;
|
||||
normal shutdown/private-directory cleanup has independent 20/20/5/5-second
|
||||
bounds, and the semantic runner has a final 180-second process bound.
|
||||
|
||||
## What was tested
|
||||
|
||||
A fresh fixture creates the original production host, encrypted opc.tcp client,
|
||||
one abandoned browse point and six event-history points. After normal client
|
||||
CloseAsync, the control verifies removal from the same running SessionManager.
|
||||
The old closed object still exposes `(1,6)` while explicitly held, as previously
|
||||
recorded; that observation is not treated as live protocol ownership.
|
||||
|
||||
A fresh valid session supplies the same open raw transport for all following
|
||||
requests. `ITransportChannel.SendRequestAsync` receives explicit request headers;
|
||||
no closed Session client guard or ClientBase header substitution can satisfy the
|
||||
negative checks. Each response must carry the exact sent RequestHandle.
|
||||
|
||||
| Request | Verified outcome |
|
||||
|---|---|
|
||||
| Fresh raw read before old-token request | Good service/item status |
|
||||
| Read with old authentication token | Correlated ServiceFault, BadSessionIdInvalid (2149908480) |
|
||||
| Fresh raw read after the fault, same transport | Good service/item status |
|
||||
| Fresh browse point creation | Good, nonempty point |
|
||||
| Old browse point from the fresh session | BadContinuationPointInvalid (2152333312) |
|
||||
| Fresh own browse point resume and release | Good; resume returns references and another point |
|
||||
| Fresh history page | Good; nonempty point; backend dispatched |
|
||||
| Old history point from the fresh session | BadContinuationPointInvalid; backend counter remains 7 to 7 |
|
||||
| Fresh own history point resume and release | Good; resume dispatches backend and returns another point |
|
||||
|
||||
All 11 raw responses were correlated. Generic transport failures/timeouts are not
|
||||
accepted as token denial. The exact .182 ClientBase independently preserves a
|
||||
nonnull AuthenticationToken in UpdateRequestHeader; the raw path bypasses that
|
||||
method entirely. The protected token getter is read through an exact-type-checked
|
||||
diagnostic accessor before close; tokens and payloads are never logged.
|
||||
|
||||
## Two distinct weak-reference boundaries
|
||||
|
||||
A NoInlining synchronous helper completes the async closed-session scope from a
|
||||
thread-pool context, returning only weak references and primitive/type metadata.
|
||||
No Session, point, response, token array or backend is returned as a strong
|
||||
reference. The first GC phase runs while the SAME original host/configuration
|
||||
remain alive. Their weak targets are explicitly expected alive. A second
|
||||
NoInlining fixture boundary completes normal host shutdown, private-directory
|
||||
cleanup and the complete async fixture scope before the outer GC phase.
|
||||
|
||||
Each phase records round 0 followed by exactly five forced blocking/compacting
|
||||
collections with fixed 50/100/250/500/1000 ms delays. Each GC/finalizer worker is
|
||||
bounded at five seconds. Observers use WeakReference.IsAlive rather than keeping
|
||||
TryGetTarget values across collections. A deliberately retained positive object
|
||||
must stay alive and an isolated collectible negative must disappear. No delay is
|
||||
extended to obtain collection.
|
||||
|
||||
In the ordinary run all **16 old client/server Session, browse point/Data,
|
||||
history-slot wrapper and history-value targets** disappeared during the first
|
||||
live-host forced collection. This separates the held-list implementation detail
|
||||
from those objects' actual reclamation in this fixture. After normal stop and
|
||||
all fixture boundaries, five server-graph targets remained across all five
|
||||
observations: server, node manager, backend, server validator and server cached
|
||||
store. Rig/client configuration/client application/client validator/client cached
|
||||
store targets disappeared. Positive and negative controls behaved correctly.
|
||||
PKI descriptors were zero in live-host and stopped-but-harness-held observations.
|
||||
The ordinary run preserves **exit 1**, with unsupported SDK2 manager-disposal
|
||||
observables still explicit.
|
||||
|
||||
For this single fixture, live-host final managed bytes were 94,550,728 and timers
|
||||
10; after-stop final managed bytes were 7,774,200 and timers 7. This drop does not
|
||||
establish that the earlier multi-restart managed/timer growth disappears, nor is
|
||||
it a usable performance denominator. Full process/framework parity remains open.
|
||||
|
||||
## Exact point-resource ownership
|
||||
|
||||
Runtime inspection identifies browse `ContinuationPoint.Data` as **Opc.Ua.NodeBrowser**
|
||||
from the original Opc.Ua.Types binary. Its exact Dispose(bool) implementation is
|
||||
empty. Its declared storage is managed IReference/List/HashSet/index state plus
|
||||
managed context/view properties, with no owned IDisposable field. The containing
|
||||
ContinuationPoint.Dispose delegates to Data, so omission of that call on this
|
||||
exact browser does not skip a direct cleanup action. This is not a statement
|
||||
about every INodeBrowser implementation or arbitrary driver browser resources.
|
||||
|
||||
The six history values are the original event HistoryContinuationState records;
|
||||
the original store saves each record directly in the SDK slot. They have scalar,
|
||||
string/date and managed paging/set state, no IDisposable contract or backend/store
|
||||
handle ownership. This event fixture has no pending raw end-bound resource. Both
|
||||
the SDK slot wrapper and its Value are weak-tracked; all collected while the
|
||||
original host remained running.
|
||||
|
||||
## Stop is distinct from terminal Dispose
|
||||
|
||||
Read-only inspection of the pinned original product/SDK establishes:
|
||||
|
||||
1. Archived OtOpcUa OpcUaApplicationHost.DisposeAsync awaits only
|
||||
ApplicationInstance.StopAsync.
|
||||
2. Original ApplicationInstance.StopAsync delegates to Server.StopAsync.
|
||||
3. ServerBase.StopAsync stops listeners/service hosts and invokes the standard
|
||||
stopping hook. StandardServer's stopping hook DOES shut down subscriptions,
|
||||
sessions and node managers and dispose internal server data.
|
||||
4. Terminal ServerBase.Dispose separately disposes its RequestQueue.
|
||||
RequestQueue owns a ServerBase reference and starts minimum worker tasks;
|
||||
those workers await SemaphoreSlim with a 15,000 ms timeout and cancellation
|
||||
token. At the minimum worker count they continue waiting. Queue.Dispose
|
||||
cancels that token, releases/disposes its signal and terminates its ownership.
|
||||
5. StandardServer.Dispose also unregisters its CertificateUpdate callback and
|
||||
disposes remaining terminal resources. The SDK2 ApplicationInstance.DisposeAsync
|
||||
explicitly performs StopAsync THEN Server.Dispose; the archived original host
|
||||
never calls that terminal API.
|
||||
|
||||
This is a source-backed original application lifecycle gap and a plausible
|
||||
retention path consistent with the observed server graph. It is not a measured
|
||||
heap dominator/root chain or attribution of any particular timer. No original
|
||||
production code was patched, and no extra disposal was added to ordinary mode.
|
||||
|
||||
A separate, gated `semantic-terminal-dispose` attribution mode first records the
|
||||
ordinary result. Only afterward does a NoInlining helper briefly acquire the
|
||||
known weak original server target, invoke its PUBLIC terminal Dispose once,
|
||||
drop that strong reference, then repeat the same fixed GC schedule. No private
|
||||
timer disposal, cache clearing, oracle adjustment or delay extension is used.
|
||||
The original ordinary exit is returned even if terminal disposal clears all
|
||||
observed targets. Its results are recorded separately in `semantic-evidence.json`.
|
||||
It cannot turn the archived original behavior or failed RSS gates into a pass.
|
||||
|
||||
That separately approved run reproduced the same normal-stop five survivors and
|
||||
returned **exit 1**. After the single public Dispose, all five disappeared at the
|
||||
first next forced collection and remained absent through round 5. At the final
|
||||
observations, timers changed from 7 to 2 and managed bytes from 7,692,144 to
|
||||
4,513,760. Positive/negative GC controls remained valid. This controlled intervention
|
||||
supports missing terminal server disposal as the ownership distinction; it does
|
||||
not identify which queue task, timer or event subscription was the actual GC root.
|
||||
It does not establish an unbounded leak from one fixture, eliminate unrelated
|
||||
native retention, or make the original process a performance denominator.
|
||||
|
||||
Both immutable adapter builds completed with zero warnings/errors, using the
|
||||
same 208 reference hashes. The ordinary run uses build 3 and the separate
|
||||
counterfactual uses build 4; their exact source, binary, build-log and raw-result
|
||||
hashes are retained in `semantic-evidence.json`. Raw evidence remains in private
|
||||
external directories. No additional control was run to adjust these findings.
|
||||
|
||||
The exact original test seams are public virtual
|
||||
`ServerBase.StopAsync(CancellationToken)`, protected virtual `Dispose(bool)`,
|
||||
`OnServerStarting(ApplicationConfiguration)`,
|
||||
`StartApplicationAsync(ApplicationConfiguration, CancellationToken)`, and
|
||||
`OnServerStoppingAsync(CancellationToken)`. Public `Dispose()` and `StartAsync`
|
||||
are nonvirtual. StandardServer overrides those protected lifecycle hooks and
|
||||
also exposes protected virtual `OnServerStarted(IServerInternal)`. A separate
|
||||
reviewed application repair can test stop failure/partial startup using these
|
||||
supported seams; this diagnostic does not repair or rebuild the archived product.
|
||||
|
||||
## Smallest future matched-host path (proposal only)
|
||||
|
||||
A standalone SDK2 driver mirroring this original standalone driver is the smallest
|
||||
path: same .NET runtime, assertions, telemetry/logging configuration, PKI/security,
|
||||
operation recipe/counts, raw request/correlation probes, NoInlining boundaries,
|
||||
weak controls, sampling schedule and module provenance. Keep SDK-specific value
|
||||
representations and read-only ownership observers explicit. Both xUnit hosts
|
||||
would require creating/porting a larger original test-host graph and introduce
|
||||
more loader/framework differences. Neither path has been implemented or approved
|
||||
as an acceptance protocol. The current candidate xUnit control is semantic
|
||||
corroboration, not process-memory comparability.
|
||||
|
||||
Any correction of archived app ownership must be a separate reviewed change and
|
||||
new provenance; these controls do not substitute a repaired baseline or use its
|
||||
post-counterfactual memory as a denominator. Long original runs, reset baselines,
|
||||
RSS caps and acceptance remain outside this work.
|
||||
@@ -1,214 +0,0 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Configuration;
|
||||
using Opc.Ua.Server;
|
||||
using Shouldly;
|
||||
using ZB.MOM.WW.OtOpcUa.Commons.OpcUa;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
using CoreHistoryReadResult = ZB.MOM.WW.OtOpcUa.Core.Abstractions.HistoryReadResult;
|
||||
return args.Length == 3 && (args[2] == "--semantic-retention-control" || args[2] == "--semantic-terminal-dispose-control")
|
||||
? await Canonical.SemanticRetentionAsync(args) : await Canonical.RunAsync(args);
|
||||
internal static partial class Canonical
|
||||
{
|
||||
private const string Scalar = BaselineRig.RawDeviceFolder + "/SoakScalar";
|
||||
private const string ArrayTag = BaselineRig.RawDeviceFolder + "/SoakArray";
|
||||
private const string UnsScalar = "SoakEquipment/Scalar";
|
||||
private static readonly DateTime Epoch = new(2026,10,1,0,0,0,DateTimeKind.Utc);
|
||||
internal static readonly OperationLedger Ledger = new();
|
||||
private static StreamWriter CurrentEvidence = null!;
|
||||
internal static async Task<int> RunAsync(string[] args)
|
||||
{
|
||||
var root=Path.GetFullPath(args[0]); var cycles=int.Parse(args[1]);
|
||||
var isolatedRestart = args.Length == 3 && args[2] == "--active-restart-control";
|
||||
if (args.Length > 3 || (args.Length == 3 && !isolatedRestart)) throw new InvalidOperationException("Unknown short-control mode");
|
||||
if(cycles<1 || cycles>4) throw new InvalidOperationException("Only a 1..4-cycle short diagnostic smoke is authorized");
|
||||
if(Directory.Exists(root)) throw new InvalidOperationException("Use a fresh private artifact directory");
|
||||
Directory.CreateDirectory(root);
|
||||
if(!OperatingSystem.IsWindows()) File.SetUnixFileMode(root,UnixFileMode.UserRead|UnixFileMode.UserWrite|UnixFileMode.UserExecute);
|
||||
await using var output=new StreamWriter(new FileStream(Path.Combine(root,"resources.jsonl"),FileMode.CreateNew,FileAccess.Write,FileShare.Read));
|
||||
CurrentEvidence=output;
|
||||
using var deadline=new CancellationTokenSource(TimeSpan.FromSeconds(120)); var ct=deadline.Token;
|
||||
var sdk=typeof(NodeId).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||
if(sdk is null || !sdk.StartsWith("1.5.378.182+",StringComparison.Ordinal)) throw new InvalidOperationException("The immutable .182 SDK is required");
|
||||
var clientRoot=Path.Combine(root,"private-fixture","client-pki");
|
||||
var telemetry=DefaultTelemetry.Create(_=>{});
|
||||
var config=new ApplicationConfiguration(telemetry)
|
||||
{
|
||||
ApplicationName="SDK2LifecycleSoak",ApplicationUri=$"urn:SDK2LifecycleSoak:{Guid.NewGuid():N}",ApplicationType=ApplicationType.Client,
|
||||
SecurityConfiguration=new SecurityConfiguration
|
||||
{
|
||||
ApplicationCertificate=new CertificateIdentifier{StoreType=CertificateStoreType.Directory,StorePath=Path.Combine(clientRoot,"own"),SubjectName="CN=SDK2LifecycleSoak"},
|
||||
TrustedIssuerCertificates=new CertificateTrustList{StoreType=CertificateStoreType.Directory,StorePath=Path.Combine(clientRoot,"issuer")},
|
||||
TrustedPeerCertificates=new CertificateTrustList{StoreType=CertificateStoreType.Directory,StorePath=Path.Combine(clientRoot,"trusted")},
|
||||
RejectedCertificateStore=new CertificateTrustList{StoreType=CertificateStoreType.Directory,StorePath=Path.Combine(clientRoot,"rejected")},AutoAcceptUntrustedCertificates=true
|
||||
},ClientConfiguration=new ClientConfiguration{DefaultSessionTimeout=15000},TransportQuotas=new TransportQuotas{OperationTimeout=5000}
|
||||
};
|
||||
var application=new ApplicationInstance(telemetry){ApplicationConfiguration=config};
|
||||
await config.ValidateAsync(ApplicationType.Client,ct);await application.CheckApplicationInstanceCertificatesAsync(true,null,ct);
|
||||
await using var rig=new BaselineRig(Path.Combine(root,"private-fixture"));
|
||||
await rig.BootAsync(ct);Configure(rig);
|
||||
var watch=Stopwatch.StartNew();var completed=0;var restarts=0;
|
||||
await LogAsync(output,new {kind="start",sdk,productRebuilt=false,sourcePublication="83ed880e",requestedCycles=cycles,
|
||||
processId=Environment.ProcessId,acceptance=false,scope="canonical operations short smoke; ownership differences remain explicit",
|
||||
unsupportedObservables=new[]{"SDK2 CertificateManager disposed flag","SDK2 manager-owned cache-clear proof","ApplicationInstance.DisposeAsync"}});
|
||||
try
|
||||
{
|
||||
if (isolatedRestart)
|
||||
{
|
||||
if (cycles != 1) throw new InvalidOperationException("The isolated restart control performs exactly one restart");
|
||||
await RestartWithActiveResourcesAsync(rig,config,ct);Configure(rig);restarts++;
|
||||
await LogAsync(output,new {kind="isolated-active-restart-completed",normalCycles=0,restarts,
|
||||
acceptance=false,ownershipParity=false,ledger=Ledger.Snapshot()});
|
||||
return 2;
|
||||
}
|
||||
while(completed<cycles)
|
||||
{
|
||||
await ExerciseAsync(rig,config,completed+1,output,ct);completed++;
|
||||
await EventuallyAsync(()=>PublicCounts(rig)==(0,0,0),ct);
|
||||
var counts=PublicCounts(rig);var fd=await BaselineMetrics.DescriptorsAsync(ct,clientRoot,rig.PkiRoot);
|
||||
fd.Pki.ShouldBe(0);
|
||||
foreach(var name in new[]{"LiveItemCount","LiveEventItemCount","MonitoredNodeCount"}) BaselineMetrics.Counter(rig.Nm,name).ShouldBe(0);
|
||||
using var process=Process.GetCurrentProcess();process.Refresh();
|
||||
await LogAsync(output,new {kind="quiescent",cycle=completed,seconds=watch.Elapsed.TotalSeconds,
|
||||
sessions=counts.Sessions,subscriptions=counts.Subscriptions,items=counts.Items,
|
||||
pkiDescriptors=fd.Pki,descriptors=fd.Total,managedBytes=GC.GetTotalMemory(true),rssBytes=process.WorkingSet64,
|
||||
serverCachedStoreReferences=BaselineMetrics.CachedStoreReferences(rig.Validator),
|
||||
clientCachedStoreReferences=BaselineMetrics.CachedStoreReferences(config.CertificateValidator),jit=System.Runtime.JitInfo.GetCompiledMethodCount(),timers=Timer.ActiveCount});
|
||||
if(completed%4==0){await RestartWithActiveResourcesAsync(rig,config,ct);Configure(rig);restarts++;}
|
||||
}
|
||||
await LogAsync(output,new {kind="operations-completed",cycles=completed,restarts,seconds=watch.Elapsed.TotalSeconds,
|
||||
acceptance=false,ownershipParity=false,reason="Original SDK has no equivalent manager-disposal observable; review required",ledger=Ledger.Snapshot()});
|
||||
return 2;
|
||||
}
|
||||
catch(Exception error)
|
||||
{
|
||||
await LogAsync(output,new {kind="failed",cycles=completed,restarts,exceptionType=error.GetType().FullName,
|
||||
uaStatus=error is ServiceResultException ua ? ua.StatusCode.ToString() : null,ledger=Ledger.Snapshot(),acceptance=false});
|
||||
Console.Error.WriteLine(error);return 1;
|
||||
}
|
||||
}
|
||||
private static int ScalarValue(Variant value)=>value.Value is int result?result:throw new InvalidOperationException("Expected scalar Int32 CLR shape");
|
||||
private static void RequirePoint(byte[]? point)=>(point is {Length:>0}).ShouldBeTrue();
|
||||
private static (int Browse,int History) ContinuationCounts(ISession session)=>BaselineMetrics.Points(session);
|
||||
private static (int Sessions,int Subscriptions,int Items) PublicCounts(BaselineRig rig)
|
||||
{var subscriptions=rig.Server.CurrentInstance.SubscriptionManager.GetSubscriptions();return(rig.Server.CurrentInstance.SessionManager.GetSessions().Count,subscriptions.Count,subscriptions.Sum(s=>s.MonitoredItemCount));}
|
||||
private static async Task EventuallyAsync(Func<bool> condition,CancellationToken ct)
|
||||
{var elapsed=Stopwatch.StartNew();while(!condition()&&elapsed.Elapsed<TimeSpan.FromSeconds(10))await Task.Delay(25,ct);condition().ShouldBeTrue();}
|
||||
private static async Task LogAsync(StreamWriter output,object value){await output.WriteLineAsync(JsonSerializer.Serialize(value));await output.FlushAsync();}
|
||||
private sealed class AcceptWrites:IOpcUaNodeWriteGateway
|
||||
{public Task<NodeWriteOutcome> WriteAsync(string id,object? value,AddressSpaceRealm realm,CancellationToken ct)=>Task.FromResult(new NodeWriteOutcome(true,null));}
|
||||
internal sealed class SqlLikeEventSource(List<HistoricalEvent> events) : IHistorianDataSource
|
||||
{
|
||||
private int _eventReads;
|
||||
internal int EventReads => Volatile.Read(ref _eventReads);
|
||||
private readonly List<HistoricalEvent> _all =
|
||||
events.OrderBy(e => e.EventTimeUtc).ThenBy(e => e.EventId, StringComparer.Ordinal).ToList();
|
||||
|
||||
public async Task<HistoricalEventsResult> ReadEventsAsync(
|
||||
string? sourceName, DateTime startUtc, DateTime endUtc, int maxEvents, CancellationToken ct)
|
||||
{
|
||||
Interlocked.Increment(ref _eventReads);
|
||||
await Task.Delay(1, ct).ConfigureAwait(false); // complete on a pool thread, like a real backend
|
||||
var window = _all.Where(e => e.EventTimeUtc >= startUtc && e.EventTimeUtc < endUtc).ToList();
|
||||
var cap = maxEvents <= 0 ? 1000 : maxEvents;
|
||||
return new HistoricalEventsResult(window.Take(cap).ToList(), window.Count > cap ? new byte[] { 1 } : null);
|
||||
}
|
||||
|
||||
public bool SupportsReverseEvents => true;
|
||||
|
||||
/// <summary>The #675 overload: reverse is <c>(lo, hi]</c> by (time, id) descending.</summary>
|
||||
public async Task<HistoricalEventsResult> ReadEventsAsync(
|
||||
string? sourceName, DateTime startUtc, DateTime endUtc, int maxEvents, bool reverse, CancellationToken ct)
|
||||
{
|
||||
if (!reverse) return await ReadEventsAsync(sourceName, startUtc, endUtc, maxEvents, ct).ConfigureAwait(false);
|
||||
await Task.Delay(1, ct).ConfigureAwait(false);
|
||||
var (lo, hi) = startUtc <= endUtc ? (startUtc, endUtc) : (endUtc, startUtc);
|
||||
var window = _all.Where(e => e.EventTimeUtc > lo && e.EventTimeUtc <= hi).Reverse().ToList();
|
||||
var cap = maxEvents <= 0 ? 1000 : maxEvents;
|
||||
return new HistoricalEventsResult(window.Take(cap).ToList(), window.Count > cap ? new byte[] { 1 } : null);
|
||||
}
|
||||
|
||||
public Task<CoreHistoryReadResult> ReadRawAsync(string r, DateTime s, DateTime e, uint m, CancellationToken ct) =>
|
||||
NullHistorianDataSource.Instance.ReadRawAsync(r, s, e, m, ct);
|
||||
public Task<CoreHistoryReadResult> ReadProcessedAsync(
|
||||
string r, DateTime s, DateTime e, TimeSpan i, HistoryAggregateType a, CancellationToken ct) =>
|
||||
NullHistorianDataSource.Instance.ReadProcessedAsync(r, s, e, i, a, ct);
|
||||
public Task<CoreHistoryReadResult> ReadAtTimeAsync(string r, IReadOnlyList<DateTime> t, CancellationToken ct) =>
|
||||
NullHistorianDataSource.Instance.ReadAtTimeAsync(r, t, ct);
|
||||
public HistorianHealthSnapshot GetHealthSnapshot() => NullHistorianDataSource.Instance.GetHealthSnapshot();
|
||||
public void Dispose() { }
|
||||
}
|
||||
/// <summary>Task-owned TCP relay. Pause blocks forwarding in both directions without closing either socket.</summary>
|
||||
private sealed class PauseProxy : IAsyncDisposable
|
||||
{
|
||||
private readonly TcpListener _listener = new(IPAddress.Loopback, 0);
|
||||
private readonly CancellationTokenSource _stop = new();
|
||||
private readonly ConcurrentBag<TcpClient> _sockets = [];
|
||||
private readonly ConcurrentBag<Task> _pumps = [];
|
||||
private readonly Task _accept;
|
||||
private TaskCompletionSource? _pause;
|
||||
internal int Port => ((IPEndPoint)_listener.LocalEndpoint).Port;
|
||||
internal PauseProxy(int targetPort)
|
||||
{
|
||||
_listener.Start();
|
||||
_accept = AcceptAsync(targetPort);
|
||||
}
|
||||
internal void Pause() => Volatile.Write(ref _pause, new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously));
|
||||
internal void Resume() => Interlocked.Exchange(ref _pause, null)?.TrySetResult();
|
||||
private async Task AcceptAsync(int port)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!_stop.IsCancellationRequested)
|
||||
{
|
||||
var incoming = await _listener.AcceptTcpClientAsync(_stop.Token);
|
||||
_sockets.Add(incoming);
|
||||
var outgoing = new TcpClient(); _sockets.Add(outgoing);
|
||||
await outgoing.ConnectAsync(IPAddress.Loopback, port, _stop.Token);
|
||||
_pumps.Add(PumpAsync(incoming.GetStream(), outgoing.GetStream()));
|
||||
_pumps.Add(PumpAsync(outgoing.GetStream(), incoming.GetStream()));
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) when (_stop.IsCancellationRequested) { }
|
||||
}
|
||||
private async Task PumpAsync(NetworkStream source, NetworkStream destination)
|
||||
{
|
||||
var buffer = new byte[16 * 1024];
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var length = await source.ReadAsync(buffer, _stop.Token);
|
||||
if (length == 0) return;
|
||||
if (Volatile.Read(ref _pause) is { } paused) await paused.Task.WaitAsync(_stop.Token);
|
||||
await destination.WriteAsync(buffer.AsMemory(0, length), _stop.Token);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException) when (_stop.IsCancellationRequested) { }
|
||||
catch (IOException) when (_stop.IsCancellationRequested) { }
|
||||
}
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
Resume(); _stop.Cancel(); _listener.Stop();
|
||||
foreach (var socket in _sockets) socket.Dispose();
|
||||
try { await _accept; await Task.WhenAll(_pumps); }
|
||||
finally { _stop.Dispose(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class OperationLedger
|
||||
{
|
||||
private readonly ConcurrentDictionary<string,long> _counts=new();
|
||||
internal void Record(string name)=>_counts.AddOrUpdate(name,1,(_,count)=>count+1);
|
||||
internal async Task<T> Call<T>(string name,Func<Task<T>> operation)
|
||||
{Record(name+".attempted");try{var value=await operation();Record(name+".returned");return value;}catch{Record(name+".faulted");throw;}}
|
||||
internal async Task Call(string name,Func<Task> operation)
|
||||
{Record(name+".attempted");try{await operation();Record(name+".returned");}catch{Record(name+".faulted");throw;}}
|
||||
internal IReadOnlyDictionary<string,long> Snapshot()=>new SortedDictionary<string,long>(_counts);
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
# Original 1.5.378.182 canonical adapter — partial diagnostic proof
|
||||
|
||||
This folder compiles a standalone diagnostic against the **unchanged original
|
||||
83ed880e published host/client DLLs**. It does not rebuild or patch product code,
|
||||
restore a substitute SDK, edit a baseline oracle, install a replacement session
|
||||
factory, or approve a performance denominator. Only short 1–4-cycle smoke runs are
|
||||
implemented. No original warmed/full/two-hour run has been performed.
|
||||
|
||||
The immutable SDK reports `1.5.378.182+6cca32dd6d79c8b57d2e00e4d2071b991d2cf71b`.
|
||||
The source workload was ported from `Sdk2LifecycleSoakTests` at `75057d8c`.
|
||||
`evidence.json` records source/input hashes, exact SDK layout and short-run results.
|
||||
Raw logs and task-owned PKI stay outside the repository; credentials are not logged.
|
||||
|
||||
## Supported operation coverage
|
||||
|
||||
`CanonicalOperations.cs` preserves the candidate's operation ordering, status
|
||||
assertions, timeouts, model, grants, event data, page size and typed-array shape.
|
||||
The representation changes are explicit: SDK2 Variant/ArrayOf helpers become the
|
||||
original Variant constructor and CLR values; ByteString becomes byte[]; and
|
||||
QualifiedName.From becomes its original constructor. There are no collection
|
||||
shims or private-state mutations.
|
||||
|
||||
| Canonical operation per normal cycle | Original short control observation |
|
||||
|---|---|
|
||||
| Two encrypted opc.tcp / SignAndEncrypt sessions, Raw/UNS URI binding | Completed |
|
||||
| One subscription, three data items, notifications | Completed |
|
||||
| One Write service with Int32/Int16[]/UNS Int32 values, three readbacks | Completed with original Good/type assertions |
|
||||
| Two browse pages, one explicit release and one abandonment | Completed; active browse count 1 |
|
||||
| History first page, foreign-session denial, resume, explicit release, six abandoned points | All 10 HistoryRead services returned; active history count 6 |
|
||||
| Writable off/on, array removal/recreation/publication | Completed |
|
||||
| Key revocation, denied read, authority restoration | Completed |
|
||||
| Paused TCP read, one-second cancellation, resume and successful recovery read | Completed; original UA status 2156134400 on the canceled read |
|
||||
| Subscription deletion/removal and address-space rebuild/reconfiguration | Completed |
|
||||
| Both normal clients CloseAsync | Both returned; version-specific post-close list comparison differs |
|
||||
| Every-fourth-cycle restart with an active session/subscription/item, browse/history points | Separate isolated one-restart control completed |
|
||||
|
||||
The failed normal control attempted one whole wire body. Its ledger records
|
||||
2 connects, 1 subscription create/apply/delete/remove, 1 Write service (3 values),
|
||||
5 ReadValue attempts (4 returned, 1 expected canceled fault), 1 revoked Read
|
||||
service, 2 Browse calls, 1 BrowseNext release, 10 HistoryRead calls, and 2 CloseAsync
|
||||
returns. Surgery, revocation, stalled-network recovery and rebuild all occurred
|
||||
before the post-close comparison. No normal cycle is reported as ownership-complete.
|
||||
|
||||
The independent active-restart control does **not** stand in for a successful
|
||||
four-cycle sequence: it starts one client/subscription/item, abandons browse and
|
||||
history points, stops/reboots the same URI/port/PKI server, and checks the captured
|
||||
old managers/sessions/subscription items and new manager counts. Those checks
|
||||
completed. It returned **exit 2**, explicitly unsupported ownership parity,
|
||||
not a green acceptance result.
|
||||
|
||||
## Close and ownership differences — unresolved
|
||||
|
||||
The first normal smoke returned **exit 1** at the copied zero-closed-list
|
||||
comparison: a retained server Session still had **1 browse / 6 history** points.
|
||||
The server SessionManager already had **zero active sessions**. A separate fixed
|
||||
250 ms read-only observation saw the same lists; the original failed comparison
|
||||
was still enforced. The first failure artifacts were left untouched.
|
||||
|
||||
Exact immutable-binary inspection explains the internal difference:
|
||||
|
||||
- SessionManager.CloseSession removes the session and calls Session.Close.
|
||||
- Session.Close only deletes its diagnostics; it does not clear continuation lists.
|
||||
- Session.Dispose clears both lists and disposes their retained values.
|
||||
- SessionManager.Shutdown/Dispose disposes sessions still in its active dictionary.
|
||||
|
||||
These are **version-specific diagnostics**, not proof that the original violates
|
||||
the wire close contract, has an unbounded leak, or retains the same objects once
|
||||
all strong diagnostic references are dropped. The adapter deliberately holds the
|
||||
old Session references while checking these fields. The SDK2 zero-list invariant
|
||||
cannot silently become a shared cross-version acceptance contract.
|
||||
|
||||
The restart control follows the different active-session shutdown path: captured
|
||||
old session/point lists and subscription items became empty. The original
|
||||
validator's cached store **references** remained 1 before and after stop. A cached
|
||||
store reference is not a count of open handles or proof of a leak.
|
||||
|
||||
Original ApplicationInstance and CertificateValidator expose no Dispose API, and
|
||||
there is no SDK2 CertificateManager/m_disposed/core-store-clear equivalent. The
|
||||
adapter reports those observables as **unsupported**, never as zero. Actual PKI
|
||||
file descriptors can be measured with the same bounded/canonical-path observer
|
||||
as the candidate; those observations cannot invent the missing manager ownership
|
||||
proof. No manual Session.Dispose, store replacement or cache clearing was added
|
||||
to make an assertion pass.
|
||||
|
||||
The historical partial proof above did not test token/continuation rejection or
|
||||
collection after dropping its diagnostic references. Later, separately reviewed
|
||||
short controls established those semantics and observed the remaining server
|
||||
graph retention after normal shutdown. Their direct point-resource inspection,
|
||||
two weak-reference phases and separate terminal-disposal attribution are recorded
|
||||
in [OWNERSHIP.md](OWNERSHIP.md) and `semantic-evidence.json`. Both ordinary failure
|
||||
results remain intact. Certificate-store/native ownership gaps remain explicit;
|
||||
these findings do not approve a common lifecycle/acceptance protocol.
|
||||
|
||||
The standalone adapter also lacks the candidate's xUnit/VSTest host; equal process
|
||||
memory overhead is not proven. Earlier original-subset managed/timer growth is an
|
||||
observation, not an approved RSS denominator or a proven SDK1 defect. Resource and
|
||||
operation parity require Astra/root review before any long run; no cap, baseline
|
||||
or acceptance protocol changes are included here.
|
||||
|
||||
## Build and short controls
|
||||
|
||||
`build.py` selects original DLLs from the provided immutable directories (host
|
||||
wins duplicate names), plus Shouldly 4.3.0/assertion dependencies only. It emits
|
||||
SHA-256 provenance and a new external project. No production project/package file
|
||||
is touched. The inventory lists exact types, fields, lifecycle APIs and MVIDs
|
||||
without creating product instances.
|
||||
|
||||
```bash
|
||||
python3 scripts/validation/opcua-lifecycle-memory/baseline-canonical/build.py \
|
||||
--host "$originalHost" --client "$originalClient" --assertions "$assertionDlls" \
|
||||
--output /tmp/original-canonical-build
|
||||
python3 scripts/validation/opcua-lifecycle-memory/baseline-canonical/run_smoke.py \
|
||||
--adapter /tmp/original-canonical-build/bin/Release/net10.0/adapter.dll \
|
||||
--output /tmp/original-canonical-close --mode normal
|
||||
python3 scripts/validation/opcua-lifecycle-memory/baseline-canonical/run_smoke.py \
|
||||
--adapter /tmp/original-canonical-build/bin/Release/net10.0/adapter.dll \
|
||||
--output /tmp/original-canonical-active-restart --mode active-restart
|
||||
```
|
||||
|
||||
Add `--inventory` to build the read-only metadata inventory instead. The runner
|
||||
uses a fresh private directory and a temporary environment credential with the
|
||||
same prefix/byte length as the canonical fixture; it preserves the original child
|
||||
exit. Exit 1 is an observed control failure; exit 2 is operations completed with
|
||||
unsupported ownership parity. Neither is a passing baseline. Normal/restart modes
|
||||
have a hard 120-second bound and no long-run option.
|
||||
|
||||
The later semantic modes are `--mode semantic-retention` and the separately gated
|
||||
`--mode semantic-terminal-dispose` attribution control. They use the 120-second
|
||||
operation deadline plus bounded independent cleanup and a 180-second outer runner
|
||||
limit. Neither changes normal/active-restart results or authorizes a long run.
|
||||
@@ -1,385 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.Json;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Opc.Ua.Configuration;
|
||||
using Shouldly;
|
||||
using ServerSession = Opc.Ua.Server.ISession;
|
||||
using ClientSession = Opc.Ua.Client.ISession;
|
||||
|
||||
internal static partial class Canonical
|
||||
{
|
||||
internal static async Task<int> SemanticRetentionAsync(string[] args)
|
||||
{
|
||||
if (args.Length != 3 || args[1] != "1") throw new InvalidOperationException("One bounded semantic control only");
|
||||
var root = Path.GetFullPath(args[0]);
|
||||
var counterfactual = args[2] == "--semantic-terminal-dispose-control";
|
||||
if (Directory.Exists(root)) throw new InvalidOperationException("Use a fresh private directory");
|
||||
Directory.CreateDirectory(root);
|
||||
if (!OperatingSystem.IsWindows()) File.SetUnixFileMode(root, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute);
|
||||
await using var output = new StreamWriter(new FileStream(Path.Combine(root, "resources.jsonl"), FileMode.CreateNew, FileAccess.Write, FileShare.Read));
|
||||
CurrentEvidence = output;
|
||||
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(120));
|
||||
var retainedPositive = new object();
|
||||
var positive = Witness("positive-retained", retainedPositive);
|
||||
var negative = EphemeralNegative();
|
||||
try
|
||||
{
|
||||
await LogAsync(output, new { kind = "semantic-process", phase = "before-fixture", process = ProcessCounters() });
|
||||
// Task.Run has no captured synchronization context. Its closure contains only path/writer/token.
|
||||
var result = await Task.Run(() => FixtureBoundary(root, output, positive, negative, deadline.Token), deadline.Token);
|
||||
var phase2 = await ObserveAsync("after-stop", result.All, positive, negative, output, deadline.Token);
|
||||
var liveOld = result.LiveHostSurvivors;
|
||||
var stopped = phase2.Where(x => x.alive && x.label != "positive-retained").Select(x => x.label).ToArray();
|
||||
await LogAsync(output, new { kind = "semantic-retention-result", semanticsComplete = true,
|
||||
liveHostOldSurvivors = liveOld, afterStopSurvivors = stopped, acceptance = false, ownershipParity = false,
|
||||
unsupportedObservables = new[] { "SDK2 CertificateManager disposed flag", "SDK2 manager-owned cache-clear proof", "ApplicationInstance.DisposeAsync" } });
|
||||
var ordinaryExitCode = liveOld.Length == 0 && stopped.Length == 0 ? 2 : 1;
|
||||
if (counterfactual)
|
||||
{
|
||||
// Separate attribution only, AFTER preserving the ordinary stop result above.
|
||||
var server = result.All.Single(x => x.Label == "fixture-server");
|
||||
var invoked = await Task.Run(() => TerminalDisposeBoundary(server), deadline.Token).WaitAsync(TimeSpan.FromSeconds(20), deadline.Token);
|
||||
await LogAsync(output, new { kind = "counterfactual-terminal-dispose", invoked, ordinaryExitCode,
|
||||
publicMethod = "ServerBase.Dispose", acceptance = false });
|
||||
var terminal = await ObserveAsync("after-terminal-dispose", result.All, positive, negative, output, deadline.Token);
|
||||
await LogAsync(output, new { kind = "counterfactual-attribution-result", ordinaryExitCode,
|
||||
survivors = terminal.Where(x => x.alive && x.label != "positive-retained").Select(x => x.label).ToArray(), acceptance = false });
|
||||
}
|
||||
GC.KeepAlive(retainedPositive);
|
||||
// Even collection of every observed target does not invent the unsupported ownership proof.
|
||||
return ordinaryExitCode;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
await LogAsync(output, new { kind = "semantic-control-failed", exceptionType = error.GetType().FullName, acceptance = false });
|
||||
Console.Error.WriteLine(error);
|
||||
GC.KeepAlive(retainedPositive);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static FixtureWitness FixtureBoundary(string root, StreamWriter output, WeakWitness positive, WeakWitness negative, CancellationToken ct) =>
|
||||
FixtureScopeAsync(root, output, positive, negative, ct).GetAwaiter().GetResult();
|
||||
|
||||
private static async Task<FixtureWitness> FixtureScopeAsync(string root, StreamWriter output, WeakWitness positive, WeakWitness negative, CancellationToken ct)
|
||||
{
|
||||
var sdk = typeof(NodeId).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||
if (sdk is null || !sdk.StartsWith("1.5.378.182+", StringComparison.Ordinal)) throw new InvalidOperationException("Immutable .182 SDK required");
|
||||
var clientRoot = Path.Combine(root, "private-fixture", "client-pki");
|
||||
BaselineRig? rig = null;
|
||||
ApplicationConfiguration? config = null;
|
||||
ApplicationInstance? application = null;
|
||||
ExceptionDispatchInfo? failure = null;
|
||||
FixtureWitness? result = null;
|
||||
var booted = false;
|
||||
try
|
||||
{
|
||||
var telemetry = DefaultTelemetry.Create(_ => { });
|
||||
config = new ApplicationConfiguration(telemetry)
|
||||
{
|
||||
ApplicationName = "SDK2LifecycleSoak", ApplicationUri = $"urn:SDK2LifecycleSoak:{Guid.NewGuid():N}", ApplicationType = ApplicationType.Client,
|
||||
SecurityConfiguration = new SecurityConfiguration
|
||||
{
|
||||
ApplicationCertificate = new CertificateIdentifier { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(clientRoot, "own"), SubjectName = "CN=SDK2LifecycleSoak" },
|
||||
TrustedIssuerCertificates = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(clientRoot, "issuer") },
|
||||
TrustedPeerCertificates = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(clientRoot, "trusted") },
|
||||
RejectedCertificateStore = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(clientRoot, "rejected") }, AutoAcceptUntrustedCertificates = true
|
||||
},
|
||||
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 15000 }, TransportQuotas = new TransportQuotas { OperationTimeout = 5000 }
|
||||
};
|
||||
application = new ApplicationInstance(telemetry) { ApplicationConfiguration = config };
|
||||
await config.ValidateAsync(ApplicationType.Client, ct);
|
||||
await application.CheckApplicationInstanceCertificatesAsync(true, null, ct);
|
||||
rig = new BaselineRig(Path.Combine(root, "private-fixture"));
|
||||
await rig.BootAsync(ct);
|
||||
Configure(rig);
|
||||
booted = true;
|
||||
await LogAsync(output, new { kind = "semantic-start", sdk, acceptance = false, productRebuilt = false,
|
||||
maximumSeconds = 120, gcDelaysMilliseconds = new[] { 50, 100, 250, 500, 1000 }, gcRoundTimeoutSeconds = 5 });
|
||||
var fixture = new List<WeakWitness>
|
||||
{
|
||||
Witness("fixture-rig", rig), Witness("fixture-server", rig.Server), Witness("fixture-node-manager", rig.Nm),
|
||||
Witness("fixture-backend", rig.Nm.HistorianDataSource), Witness("fixture-client-config", config),
|
||||
Witness("fixture-client-application", application), Witness("fixture-server-validator", rig.Validator),
|
||||
Witness("fixture-client-validator", config.CertificateValidator)
|
||||
};
|
||||
// This synchronous NoInlining boundary drops the completed async state machine before phase1 GC.
|
||||
var closed = ClosedBoundary(rig, config, output, ct);
|
||||
PublicCounts(rig).ShouldBe((0, 0, 0));
|
||||
// Validation may populate stores on first connection; inspect after those operations.
|
||||
CaptureStores(rig.Validator, "fixture-server-store", fixture);
|
||||
CaptureStores(config.CertificateValidator, "fixture-client-store", fixture);
|
||||
var all = closed.Concat(fixture).ToArray();
|
||||
await WriteShapes(all, output);
|
||||
var phase1 = await ObserveAsync("live-host", all, positive, negative, output, ct);
|
||||
var survivors = phase1.Where(x => x.alive && x.label.StartsWith("old-", StringComparison.Ordinal)).Select(x => x.label).ToArray();
|
||||
foreach (var live in phase1.Where(x => x.label.StartsWith("fixture-", StringComparison.Ordinal)))
|
||||
live.alive.ShouldBeTrue("the host/configuration are intentionally still owned in phase1");
|
||||
var descriptors = await BaselineMetrics.DescriptorsAsync(ct, clientRoot, rig.PkiRoot);
|
||||
descriptors.Pki.ShouldBe(0);
|
||||
await LogAsync(output, new { kind = "semantic-owned-resources", phase = "live-host", pkiDescriptors = descriptors.Pki,
|
||||
serverCachedStoreReferences = BaselineMetrics.CachedStoreReferences(rig.Validator),
|
||||
clientCachedStoreReferences = BaselineMetrics.CachedStoreReferences(config.CertificateValidator),
|
||||
cachedReferenceIsOpenHandle = false });
|
||||
result = new FixtureWitness(all, survivors);
|
||||
}
|
||||
catch (Exception error) { failure = ExceptionDispatchInfo.Capture(error); }
|
||||
finally
|
||||
{
|
||||
// These bounds do not reuse the canceled 120-second operation token.
|
||||
async Task Cleanup(string step, Func<Task> operation, int seconds)
|
||||
{
|
||||
try { await operation().WaitAsync(TimeSpan.FromSeconds(seconds), CancellationToken.None); }
|
||||
catch (Exception error)
|
||||
{
|
||||
failure ??= ExceptionDispatchInfo.Capture(error);
|
||||
await LogAsync(output, new { kind = "semantic-cleanup-failed", step, exceptionType = error.GetType().FullName });
|
||||
}
|
||||
}
|
||||
if (rig is not null)
|
||||
await Cleanup("normal-host-stop", () => rig.DisposeAsync().AsTask(), 20);
|
||||
if (booted && rig is not null && config is not null)
|
||||
await Cleanup("post-stop-observations", async () =>
|
||||
{
|
||||
using var probe = new CancellationTokenSource(TimeSpan.FromSeconds(15));
|
||||
var after = await BaselineMetrics.DescriptorsAsync(probe.Token, clientRoot, rig.PkiRoot);
|
||||
after.Pki.ShouldBe(0);
|
||||
await LogAsync(output, new { kind = "semantic-owned-resources", phase = "stopped-but-harness-held", pkiDescriptors = after.Pki,
|
||||
serverCachedStoreReferences = BaselineMetrics.CachedStoreReferences(rig.Validator),
|
||||
clientCachedStoreReferences = BaselineMetrics.CachedStoreReferences(config.CertificateValidator), disposalFlagObservable = false });
|
||||
}, 20);
|
||||
await Cleanup("client-private-directory", () => Task.Run(() => { if (Directory.Exists(clientRoot)) Directory.Delete(clientRoot, true); }), 5);
|
||||
if (rig is not null)
|
||||
await Cleanup("server-private-directory", () => Task.Run(() => { if (Directory.Exists(rig.PkiRoot)) Directory.Delete(rig.PkiRoot, true); }), 5);
|
||||
GC.KeepAlive(application); GC.KeepAlive(config); GC.KeepAlive(rig);
|
||||
}
|
||||
failure?.Throw();
|
||||
return result ?? throw new InvalidOperationException("The fixture did not produce diagnostic witnesses");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakWitness[] ClosedBoundary(BaselineRig rig, ApplicationConfiguration config, StreamWriter output, CancellationToken ct) =>
|
||||
ClosedScopeAsync(rig, config, output, ct).GetAwaiter().GetResult();
|
||||
|
||||
private static async Task<WeakWitness[]> ClosedScopeAsync(BaselineRig rig, ApplicationConfiguration config, StreamWriter output, CancellationToken ct)
|
||||
{
|
||||
var weak = new List<WeakWitness>();
|
||||
using var owner = await ConnectAsync(rig, config, null, ct);
|
||||
weak.Add(Witness("old-client-session", owner));
|
||||
var oldServerSession = rig.Server.CurrentInstance.SessionManager.GetSessions().Single(x => x.Id == owner.SessionId);
|
||||
weak.Add(Witness("old-server-session", oldServerSession));
|
||||
var oldAuthenticationToken = Token(owner);
|
||||
var oldBrowse = (await BrowseAsync(owner, ct))!;
|
||||
RequirePoint(oldBrowse);
|
||||
byte[]? oldHistory = null;
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
var page = await PageAsync(owner, null, false, ct);
|
||||
RequirePoint(page.ContinuationPoint);
|
||||
oldHistory ??= page.ContinuationPoint;
|
||||
}
|
||||
CapturePoints(oldServerSession, weak);
|
||||
ContinuationCounts(oldServerSession).ShouldBe((1, 6));
|
||||
await owner.CloseAsync(ct);
|
||||
rig.Server.CurrentInstance.SessionManager.GetSessions().Any(x => ReferenceEquals(x, oldServerSession)).ShouldBeFalse();
|
||||
rig.Server.CurrentInstance.SessionManager.GetSessions().Count.ShouldBe(0);
|
||||
await LogAsync(output, new { kind = "semantic-closed-state", activeSessions = 0, rawClosedBrowse = ContinuationCounts(oldServerSession).Browse,
|
||||
rawClosedHistory = ContinuationCounts(oldServerSession).History, diagnosticReferenceHeld = true });
|
||||
using var fresh = await ConnectAsync(rig, config, null, ct);
|
||||
var channel = fresh.TransportChannel;
|
||||
var freshToken = Token(fresh);
|
||||
freshToken.ShouldNotBe(oldAuthenticationToken);
|
||||
uint sequence = 10000;
|
||||
RequestHeader Header(NodeId token) => new() { AuthenticationToken = token, RequestHandle = ++sequence, Timestamp = DateTime.UtcNow, TimeoutHint = 5000 };
|
||||
ReadRequest Read(NodeId token) => new() { RequestHeader = Header(token), TimestampsToReturn = TimestampsToReturn.Neither,
|
||||
NodesToRead = [new ReadValueId { NodeId = Raw(fresh, Scalar), AttributeId = Attributes.Value }] };
|
||||
await RequireReadGood(channel, Read(freshToken), "fresh-read-before", output, ct);
|
||||
var oldRequest = Read(oldAuthenticationToken);
|
||||
var denied = await Send(channel, oldRequest, "old-authentication-token", output, ct);
|
||||
var deniedCode = denied.ResponseHeader.ServiceResult;
|
||||
(deniedCode == StatusCodes.BadSessionIdInvalid || deniedCode == StatusCodes.BadSessionClosed).ShouldBeTrue();
|
||||
await RequireReadGood(channel, Read(freshToken), "fresh-read-after", output, ct);
|
||||
|
||||
var ownBrowseRequest = new BrowseRequest { RequestHeader = Header(freshToken), RequestedMaxReferencesPerNode = 1,
|
||||
NodesToBrowse = [new BrowseDescription { NodeId = Raw(fresh, BaselineRig.RawDeviceFolder), BrowseDirection = BrowseDirection.Forward,
|
||||
ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences, IncludeSubtypes = true, ResultMask = (uint)BrowseResultMask.All }] };
|
||||
var ownBrowse = (BrowseResponse)await Send(channel, ownBrowseRequest, "fresh-own-browse", output, ct);
|
||||
ownBrowse.Results[0].StatusCode.ShouldBe(StatusCodes.Good); RequirePoint(ownBrowse.Results[0].ContinuationPoint);
|
||||
var oldBrowseResponse = (BrowseNextResponse)await Send(channel, new BrowseNextRequest { RequestHeader = Header(freshToken),
|
||||
ContinuationPoints = [oldBrowse], ReleaseContinuationPoints = false }, "old-browse-point", output, ct);
|
||||
oldBrowseResponse.Results[0].StatusCode.ShouldBe(StatusCodes.BadContinuationPointInvalid);
|
||||
await LogAsync(output, new { kind = "semantic-item-status", name = "old-browse-point", statusCode = (uint)oldBrowseResponse.Results[0].StatusCode });
|
||||
var ownBrowseNext = (BrowseNextResponse)await Send(channel, new BrowseNextRequest { RequestHeader = Header(freshToken),
|
||||
ContinuationPoints = [ownBrowse.Results[0].ContinuationPoint], ReleaseContinuationPoints = false }, "fresh-own-browse-resume", output, ct);
|
||||
ownBrowseNext.Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
ownBrowseNext.Results[0].References.Count.ShouldBeGreaterThan(0); RequirePoint(ownBrowseNext.Results[0].ContinuationPoint);
|
||||
var ownBrowseRelease = (BrowseNextResponse)await Send(channel, new BrowseNextRequest { RequestHeader = Header(freshToken),
|
||||
ContinuationPoints = [ownBrowseNext.Results[0].ContinuationPoint], ReleaseContinuationPoints = true }, "fresh-own-browse-release", output, ct);
|
||||
ownBrowseRelease.Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
|
||||
HistoryReadRequest History(byte[]? point, bool release) => new()
|
||||
{
|
||||
RequestHeader = Header(freshToken), TimestampsToReturn = TimestampsToReturn.Both, ReleaseContinuationPoints = release,
|
||||
HistoryReadDetails = new ExtensionObject(new ReadEventDetails { StartTime = Epoch.AddDays(-1), EndTime = Epoch.AddDays(1), NumValuesPerNode = 4,
|
||||
Filter = new EventFilter { SelectClauses = [new SimpleAttributeOperand(ObjectTypeIds.BaseEventType, new QualifiedName(BrowseNames.EventId))] } }),
|
||||
NodesToRead = [new HistoryReadValueId { NodeId = Raw(fresh, BaselineRig.RawDeviceFolder), ContinuationPoint = point }]
|
||||
};
|
||||
var backend = (SqlLikeEventSource)rig.Nm.HistorianDataSource;
|
||||
var beforeOwn = backend.EventReads;
|
||||
var ownHistory = (HistoryReadResponse)await Send(channel, History(null, false), "fresh-own-history", output, ct);
|
||||
ownHistory.Results[0].StatusCode.ShouldBe(StatusCodes.Good); RequirePoint(ownHistory.Results[0].ContinuationPoint);
|
||||
backend.EventReads.ShouldBeGreaterThan(beforeOwn);
|
||||
var beforeOld = backend.EventReads;
|
||||
var oldHistoryResponse = (HistoryReadResponse)await Send(channel, History(oldHistory, false), "old-history-point", output, ct);
|
||||
oldHistoryResponse.Results[0].StatusCode.ShouldBe(StatusCodes.BadContinuationPointInvalid);
|
||||
backend.EventReads.ShouldBe(beforeOld);
|
||||
await LogAsync(output, new { kind = "semantic-backend", operation = "old-history-point", before = beforeOld, after = backend.EventReads,
|
||||
statusCode = (uint)oldHistoryResponse.Results[0].StatusCode });
|
||||
var ownHistoryNext = (HistoryReadResponse)await Send(channel, History(ownHistory.Results[0].ContinuationPoint, false), "fresh-own-history-resume", output, ct);
|
||||
ownHistoryNext.Results[0].StatusCode.ShouldBe(StatusCodes.Good); RequirePoint(ownHistoryNext.Results[0].ContinuationPoint);
|
||||
backend.EventReads.ShouldBeGreaterThan(beforeOld);
|
||||
var releaseHistory = (HistoryReadResponse)await Send(channel, History(ownHistoryNext.Results[0].ContinuationPoint, true), "fresh-own-history-release", output, ct);
|
||||
releaseHistory.Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
await fresh.CloseAsync(ct);
|
||||
rig.Server.CurrentInstance.SessionManager.GetSessions().Count.ShouldBe(0);
|
||||
return weak.ToArray();
|
||||
}
|
||||
|
||||
private static NodeId Token(ClientSession session)
|
||||
{
|
||||
var property = typeof(ClientBase).GetProperty("AuthenticationToken", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("Exact .182 token getter is missing");
|
||||
return property.PropertyType == typeof(NodeId) && property.GetValue(session) is NodeId value && !NodeId.IsNull(value)
|
||||
? NodeId.Parse(value.ToString()) : throw new InvalidOperationException("Exact .182 token getter changed");
|
||||
}
|
||||
private static async Task<IServiceResponse> Send(ITransportChannel channel, IServiceRequest request, string name, StreamWriter output, CancellationToken ct)
|
||||
{
|
||||
// No Session closed guard or ClientBase header update runs on this public raw transport path.
|
||||
var response = await channel.SendRequestAsync(request, ct);
|
||||
response.ResponseHeader.RequestHandle.ShouldBe(request.RequestHeader.RequestHandle);
|
||||
await LogAsync(output, new { kind = "semantic-wire", name, requestHandle = request.RequestHeader.RequestHandle,
|
||||
responseHandle = response.ResponseHeader.RequestHandle, responseType = response.GetType().Name,
|
||||
serviceStatusCode = (uint)response.ResponseHeader.ServiceResult });
|
||||
return response;
|
||||
}
|
||||
private static async Task RequireReadGood(ITransportChannel channel, ReadRequest request, string name, StreamWriter output, CancellationToken ct)
|
||||
{
|
||||
var response = (ReadResponse)await Send(channel, request, name, output, ct);
|
||||
response.ResponseHeader.ServiceResult.ShouldBe(StatusCodes.Good);
|
||||
response.Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
}
|
||||
|
||||
private static FieldInfo ExactField(object owner, string name)
|
||||
{
|
||||
for (var type = owner.GetType(); type is not null; type = type.BaseType)
|
||||
if (type.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly) is { } field) return field;
|
||||
throw new InvalidOperationException("Missing exact .182 diagnostic field: " + name);
|
||||
}
|
||||
private static void CapturePoints(ServerSession session, List<WeakWitness> target)
|
||||
{
|
||||
var gate = ExactField(session, "m_lock").GetValue(session) as System.Threading.Lock ?? throw new InvalidOperationException("Unexpected session lock");
|
||||
using (gate.EnterScope())
|
||||
{
|
||||
var browse = ExactField(session, "m_browseContinuationPoints").GetValue(session) as IList ?? throw new InvalidOperationException("Missing populated browse list");
|
||||
foreach (var value in browse)
|
||||
{
|
||||
var point = value as Opc.Ua.Server.ContinuationPoint ?? throw new InvalidOperationException("Unexpected browse point type");
|
||||
target.Add(Witness("old-browse-point", point));
|
||||
if (point.Data is { } data) target.Add(Witness("old-browse-data", data));
|
||||
}
|
||||
var history = ExactField(session, "m_historyContinuationPoints").GetValue(session) as IList ?? throw new InvalidOperationException("Missing populated history list");
|
||||
var index = 0;
|
||||
foreach (var value in history)
|
||||
{
|
||||
var slot = value ?? throw new InvalidOperationException("Null history slot");
|
||||
target.Add(Witness("old-history-slot-" + index, slot));
|
||||
var state = ExactField(slot, "Value").GetValue(slot) ?? throw new InvalidOperationException("Null history state");
|
||||
target.Add(Witness("old-history-value-" + index++, state));
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void CaptureStores(CertificateValidator validator, string label, List<WeakWitness> target)
|
||||
{
|
||||
var gate = ExactField(validator, "m_semaphore").GetValue(validator) as SemaphoreSlim ?? throw new InvalidOperationException("Unexpected validator lock");
|
||||
if (!gate.Wait(TimeSpan.FromSeconds(5))) throw new TimeoutException("Validator witness lock timed out");
|
||||
try
|
||||
{
|
||||
var index = 0;
|
||||
foreach (var name in new[] { "m_trustedCertificateStore", "m_issuerCertificateStore", "m_rejectedCertificateStore" })
|
||||
if (ExactField(validator, name).GetValue(validator) is CertificateStoreIdentifier identifier
|
||||
&& ExactField(identifier, "m_store").GetValue(identifier) is ICertificateStore store)
|
||||
target.Add(Witness(label + "-" + index++, store));
|
||||
}
|
||||
finally { gate.Release(); }
|
||||
}
|
||||
private static WeakWitness Witness(string label, object target) => new(label, target);
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakWitness EphemeralNegative() => Witness("negative-collectible", new object());
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static bool TerminalDisposeBoundary(WeakWitness server) => server.DisposeOriginalServerForAttribution();
|
||||
private static async Task WriteShapes(IEnumerable<WeakWitness> witnesses, StreamWriter output)
|
||||
{ foreach (var witness in witnesses) await LogAsync(output, witness.Shape); }
|
||||
private static async Task<WeakObservation[]> ObserveAsync(string phase, WeakWitness[] witnesses, WeakWitness positive, WeakWitness negative, StreamWriter output, CancellationToken ct)
|
||||
{
|
||||
var delays = new[] { 0, 50, 100, 250, 500, 1000 };
|
||||
WeakObservation[] last = [];
|
||||
for (var round = 0; round < delays.Length; round++)
|
||||
{
|
||||
if (round > 0)
|
||||
{
|
||||
await Task.Delay(delays[round], ct);
|
||||
await Task.Run(ForcedCollection, ct).WaitAsync(TimeSpan.FromSeconds(5), ct);
|
||||
}
|
||||
last = witnesses.Concat([positive, negative]).Select(x => x.Observe(phase == "live-host" && x.Label.StartsWith("fixture-", StringComparison.Ordinal)
|
||||
|| x.Label == "positive-retained")).ToArray();
|
||||
await LogAsync(output, new { kind = "weak-observation", phase, round, groups = last, process = ProcessCounters() });
|
||||
positive.IsAlive().ShouldBeTrue("the retained positive must remain observable");
|
||||
if (round > 0) negative.IsAlive().ShouldBeFalse("the isolated collectible negative proves GC observation is effective");
|
||||
}
|
||||
return last;
|
||||
}
|
||||
private static void ForcedCollection() { GC.Collect(2, GCCollectionMode.Forced, true, true); GC.WaitForPendingFinalizers(); GC.Collect(2, GCCollectionMode.Forced, true, true); }
|
||||
private static object ProcessCounters()
|
||||
{
|
||||
using var process = Process.GetCurrentProcess(); process.Refresh();
|
||||
return new { managedBytes = GC.GetTotalMemory(false), rssBytes = process.WorkingSet64,
|
||||
activeTimers = Timer.ActiveCount, gcCommittedBytes = GC.GetGCMemoryInfo().TotalCommittedBytes,
|
||||
jitMethods = System.Runtime.JitInfo.GetCompiledMethodCount() };
|
||||
}
|
||||
private sealed class WeakWitness
|
||||
{
|
||||
private readonly WeakReference _reference;
|
||||
internal string Label { get; }
|
||||
internal object Shape { get; }
|
||||
private readonly string _type;
|
||||
internal WeakWitness(string label, object target)
|
||||
{
|
||||
Label = label; _type = target.GetType().FullName ?? target.GetType().Name; _reference = new WeakReference(target);
|
||||
var fields = new List<object>();
|
||||
for (var type = target.GetType(); type is not null; type = type.BaseType)
|
||||
foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
|
||||
if (typeof(IDisposable).IsAssignableFrom(field.FieldType)) fields.Add(new { name = field.Name, type = field.FieldType.FullName });
|
||||
Shape = new { kind = "weak-resource-shape", label, type = _type, isDisposable = target is IDisposable, resourceFields = fields };
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.NoInlining)] internal bool IsAlive() => _reference.IsAlive;
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
internal bool DisposeOriginalServerForAttribution()
|
||||
{
|
||||
var value = _reference.Target;
|
||||
if (value is null) return false;
|
||||
if (Label != "fixture-server" || value is not ZB.MOM.WW.OtOpcUa.OpcUaServer.OtOpcUaSdkServer server)
|
||||
throw new InvalidOperationException("Only the known original server may receive terminal attribution disposal");
|
||||
server.Dispose(); // Public terminal lifecycle API, once; no private timer/cache manipulation.
|
||||
return true;
|
||||
}
|
||||
internal WeakObservation Observe(bool expectedAlive) => new(Label, _type, IsAlive(), expectedAlive);
|
||||
}
|
||||
private sealed record WeakObservation(string label, string type, bool alive, bool expectedAlive);
|
||||
private sealed record FixtureWitness(WeakWitness[] All, string[] LiveHostSurvivors);
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Compile diagnostic adapters against the immutable original publication; never build product code."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--host', type=Path, required=True)
|
||||
parser.add_argument('--client', type=Path, required=True)
|
||||
parser.add_argument('--assertions', type=Path, required=True, help='Directory containing Shouldly.dll; only assertion dependencies are selected')
|
||||
parser.add_argument('--output', type=Path, required=True)
|
||||
parser.add_argument('--inventory', action='store_true')
|
||||
args = parser.parse_args()
|
||||
root = args.output.resolve(); root.mkdir(parents=True, exist_ok=False)
|
||||
source = Path(__file__).resolve().parent
|
||||
references = {}
|
||||
for directory in [args.host, args.client]:
|
||||
for dll in sorted(directory.resolve(strict=True).glob('*.dll')):
|
||||
references.setdefault(dll.name, dll)
|
||||
for name in ['Shouldly.dll', 'DiffEngine.dll', 'EmptyFiles.Xml.dll']:
|
||||
path = args.assertions.resolve(strict=True) / name
|
||||
if path.exists(): references.setdefault(name, path)
|
||||
project = ET.Element('Project', Sdk='Microsoft.NET.Sdk')
|
||||
properties = ET.SubElement(project, 'PropertyGroup')
|
||||
for key,value in {'OutputType':'Exe','TargetFramework':'net10.0','Nullable':'enable','ImplicitUsings':'enable',
|
||||
'TreatWarningsAsErrors':'true','EnableDefaultCompileItems':'false'}.items():
|
||||
ET.SubElement(properties,key).text=value
|
||||
items = ET.SubElement(project,'ItemGroup')
|
||||
ET.SubElement(items,'FrameworkReference',Include='Microsoft.AspNetCore.App')
|
||||
for name,path in references.items():
|
||||
reference=ET.SubElement(items,'Reference',Include=path.stem); ET.SubElement(reference,'HintPath').text=str(path)
|
||||
files = ['Inventory.cs'] if args.inventory else ['Program.cs','BaselineRig.cs','BaselineMetrics.cs','CanonicalOperations.cs','SemanticRetention.cs']
|
||||
for name in files: ET.SubElement(items,'Compile',Include=str(source/name))
|
||||
path=root/'adapter.csproj'; ET.indent(project); ET.ElementTree(project).write(path,encoding='unicode')
|
||||
manifest={'diagnosticOnly':True,'productRebuilt':False,'references':{name:hashlib.sha256(p.read_bytes()).hexdigest() for name,p in references.items()},
|
||||
'sources':{name:hashlib.sha256((source/name).read_bytes()).hexdigest() for name in files}}
|
||||
(root/'provenance.json').write_text(json.dumps(manifest,indent=2)+'\n')
|
||||
with (root/'build.log').open('w') as log:
|
||||
result=subprocess.run(['dotnet','build',str(path),'-c','Release','-m:2'],stdout=log,stderr=subprocess.STDOUT)
|
||||
raise SystemExit(result.returncode)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run one bounded original-only diagnostic control; preserve failures and unsupported exit 2."""
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import secrets
|
||||
import subprocess
|
||||
|
||||
parser=argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--adapter',type=Path,required=True)
|
||||
parser.add_argument('--output',type=Path,required=True)
|
||||
parser.add_argument('--mode',choices=['normal','active-restart','semantic-retention','semantic-terminal-dispose'],required=True)
|
||||
args=parser.parse_args()
|
||||
output=args.output.resolve()
|
||||
if output.exists():raise RuntimeError('Use a fresh private output directory')
|
||||
log=output.with_suffix('.log')
|
||||
environment=os.environ.copy()
|
||||
environment['OTOPCUA_BASELINE_CANONICAL_KEY']='otua_k-server-events_'+secrets.token_hex(3)
|
||||
command=['dotnet',str(args.adapter.resolve(strict=True)),str(output),'1']
|
||||
if args.mode=='active-restart':command+=['--active-restart-control']
|
||||
if args.mode=='semantic-retention':command+=['--semantic-retention-control']
|
||||
if args.mode=='semantic-terminal-dispose':command+=['--semantic-terminal-dispose-control']
|
||||
outer_timeout=180 if args.mode.startswith('semantic-') else 120
|
||||
with os.fdopen(os.open(log,os.O_WRONLY|os.O_CREAT|os.O_EXCL,0o600),'w') as stream:
|
||||
try:result=subprocess.run(command,env=environment,stdout=stream,stderr=subprocess.STDOUT,timeout=outer_timeout);exit_code=result.returncode
|
||||
except subprocess.TimeoutExpired:exit_code=124
|
||||
if output.exists():
|
||||
(output/'runner-receipt.json').write_text(json.dumps({'mode':args.mode,'exitCode':exit_code,'acceptance':False,
|
||||
'productRebuilt':False,'timeoutSeconds':outer_timeout,'credentialBytes':len(environment['OTOPCUA_BASELINE_CANONICAL_KEY'].encode())},indent=2)+'\n')
|
||||
print(json.dumps({'mode':args.mode,'exitCode':exit_code,'acceptance':False}))
|
||||
raise SystemExit(exit_code)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,71 +0,0 @@
|
||||
# Linux late-slope diagnostic
|
||||
|
||||
The [protocol](../LATE_SLOPE.md) fixes 7,200 seconds of canonical cycling from
|
||||
startup completion, with the existing active restart every fourth cycle. The
|
||||
cycle-three baseline and resource caps remain in force. A latched rejection
|
||||
keeps the original failing test and container exit. The result records
|
||||
`acceptance=false` even when the diagnostic completes its duration and shutdown.
|
||||
|
||||
The analyzer requires an ordered active, recovered-stall, resource-observation,
|
||||
quiescent and complete-cycle ledger. It checks the 25-second restart helper
|
||||
bound, 30-second complete cycle bound and 60-second shutdown bound. It
|
||||
recomputes the first cold rejection and verifies its assertion against the
|
||||
actual TRX. It checks each fixed time window and the entire 1,800–7,200 second
|
||||
range before reporting RSS and retained-managed slopes in bytes per hour.
|
||||
The report includes sample counts, quiescent peaks, final values and coverage.
|
||||
It identifies whether the earlier saturation workload had completed by 1,800
|
||||
seconds, which bounds any interpretation relative to the previously observed
|
||||
restart step. The raw JSONL keeps every sample and the first assertion stack.
|
||||
|
||||
Certificate allocation stack tracking remains enabled and contributes to the
|
||||
measured process. The slope report is descriptive and carries no resource
|
||||
pass threshold. Quiescent peaks refer to the sampled points.
|
||||
|
||||
## Offline controls and artifact preparation
|
||||
|
||||
The synthetic controls exercise the parser, receipts and bundle manifest with
|
||||
temporary files. Run them with Python 3.11 or later.
|
||||
|
||||
```bash
|
||||
python3 scripts/validation/opcua-lifecycle-memory/late-slope/test_offline.py
|
||||
```
|
||||
|
||||
Prepare from the reviewed clean commit containing the canonical test and tools.
|
||||
The image argument is the immutable ID of a locally cached Linux ARM64 SDK
|
||||
image. The explicitly selected Docker context must use a local Unix socket.
|
||||
The preparation command publishes the self-contained .NET 10.0.14 app and
|
||||
records the exact SDK 2.0.1 and HistorianGateway 1.0.0 graph, source hashes, file
|
||||
hashes and managed module MVIDs. It uses the repository's read-only PE metadata
|
||||
inspector. Preparation completes before any descriptor or lifecycle test runs.
|
||||
|
||||
```bash
|
||||
python3 scripts/validation/opcua-lifecycle-memory/late-slope/prepare.py \
|
||||
--source-revision "$reviewedRevision" --docker-context "$localContext" \
|
||||
--image "$cachedImageId" --output "$bundle"
|
||||
python3 "$bundle/tools/launch.py" --bundle "$bundle" \
|
||||
--receipt-sha256 "$reviewedBundleReceiptHash" --verify-only
|
||||
```
|
||||
|
||||
## Reviewed run and analysis
|
||||
|
||||
Root owns launch after review of the exact bundle receipt and controls. The
|
||||
bundled launcher uses the pinned Unix endpoint, immutable image, network-none
|
||||
container, read-only root filesystem and read-only application and tools mounts.
|
||||
A fresh private task directory holds results and fixture files. The two
|
||||
descriptor controls must execute successfully before the canonical test starts. The launcher verifies
|
||||
the actual test process's apphost, mapped CLR and CLR hash. Its outer deadline
|
||||
is 7,440 seconds, with cleanup limited to the uniquely labeled container.
|
||||
|
||||
```bash
|
||||
python3 "$bundle/tools/launch.py" --bundle "$bundle" \
|
||||
--receipt-sha256 "$reviewedBundleReceiptHash" --output "$run"
|
||||
python3 "$bundle/tools/analyze.py" --run "$run" \
|
||||
--bundle-receipt "$bundle/receipt.json" --bundle-receipt-sha256 "$reviewedBundleReceiptHash"
|
||||
```
|
||||
|
||||
A completed diagnostic with a cold-cap rejection has a nonzero launcher exit.
|
||||
Its receipt records diagnostic completion separately from the actual test and
|
||||
container status. The offline analyzer verifies the reviewed bundle receipt,
|
||||
raw evidence hashes, test identities and outcomes, fixed duration and verified
|
||||
shutdown before emitting a report. It can run from copies of the small bundle
|
||||
receipt and run evidence on a machine without Docker.
|
||||
@@ -1,423 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate a recorded Linux late-slope diagnostic and describe its quiescent samples."""
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
from pathlib import Path
|
||||
import re
|
||||
from statistics import median
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
PROTOCOL = "sdk2-late-slope-v1"
|
||||
DOCKER_LABEL = "org.otopcua.late-slope-run"
|
||||
MODE = "late-slope"
|
||||
SECONDS = 7200
|
||||
MAX_CYCLE_SECONDS = 30
|
||||
RESTART_SECONDS = 25
|
||||
SHUTDOWN_SECONDS = 60
|
||||
CONTAINER_SECONDS = 7440
|
||||
RUNTIME = "10.0.14"
|
||||
SDK = "2.0.1+07e62f72500cc0923a2bab940653c8c1116fa286"
|
||||
APP = "ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests"
|
||||
TEST_CLASS = APP + ".Sdk2LifecycleSoakTests."
|
||||
TEST_NAME = TEST_CLASS + "Repeated_lifecycles_return_resources_to_a_steady_baseline"
|
||||
DESCRIPTOR_TESTS = {
|
||||
TEST_CLASS + "Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close",
|
||||
TEST_CLASS + "Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open",
|
||||
}
|
||||
STALL_STATUSES = {"OperationCanceled", "BadTimeout", "BadRequestCancelledByClient", "BadRequestTimeout", "BadRequestInterrupted"}
|
||||
WINDOWS = ((1800, 2400), (3600, 4200), (6600, 7200))
|
||||
BUDGETS = {"fdGrowth": 32, "retainedManagedGrowthBytes": 64 << 20, "rssGrowthBytes": 128 << 20}
|
||||
SETTINGS = {
|
||||
"protocol": PROTOCOL, "mode": MODE, "requestedSeconds": SECONDS, "rid": "linux-arm64",
|
||||
"runtimeVersion": RUNTIME, "selfContained": True, "acceptance": False,
|
||||
"startupTimeoutSeconds": 120, "cycleTimeoutSeconds": MAX_CYCLE_SECONDS,
|
||||
"cycleDeadlineSeconds": SECONDS + MAX_CYCLE_SECONDS, "restartTimeoutSeconds": RESTART_SECONDS,
|
||||
"ownerTimeoutSeconds": 20, "shutdownTimeoutSeconds": SHUTDOWN_SECONDS,
|
||||
"containerTimeoutSeconds": CONTAINER_SECONDS, "certificateLeakTracking": True,
|
||||
"windowsSeconds": [list(window) for window in WINDOWS], "limits": BUDGETS,
|
||||
}
|
||||
CAP_FIELDS = (("Descriptors", "fdGrowth"), ("ManagedBytes", "retainedManagedGrowthBytes"), ("RssBytes", "rssGrowthBytes"))
|
||||
ZERO_FIELDS = (
|
||||
"Sessions", "Subscriptions", "Items", "BrowsePoints", "HistoryPoints",
|
||||
"LiveDataItems", "LiveEventItems", "MonitoredNodes", "PkiDescriptors",
|
||||
)
|
||||
STEADY_FIELDS = ("Variables", "Folders", "Conditions", "CachedCertificateStores")
|
||||
MEASUREMENTS = (
|
||||
"Descriptors", "ManagedBytes", "RssBytes", "AllocatedBytes", "Gen0", "Gen1", "Gen2",
|
||||
"GcCommittedBytes", "GcHeapBytes", "GcFragmentedBytes", "PinnedObjects", "PendingFinalizers",
|
||||
"JitMethods", "JitIlBytes", "ActiveTimers", "Threads",
|
||||
)
|
||||
SAMPLE_FIELDS = {"Cycle", "Seconds", *ZERO_FIELDS, *STEADY_FIELDS, *MEASUREMENTS}
|
||||
EVIDENCE_FILES = (
|
||||
"launch.json", "container.log", "container-exit-status.txt", "controller-runtime.txt",
|
||||
"descriptor-controls.log", "test.log", "target-runtime.txt", "resources.jsonl",
|
||||
"test-exit-status.txt", "results/descriptor-controls.trx", "results/late-slope.trx",
|
||||
)
|
||||
TRX = {"t": "http://microsoft.com/schemas/VisualStudio/TeamTest/2010"}
|
||||
|
||||
|
||||
def require(condition, message):
|
||||
if not condition:
|
||||
raise ValueError(message)
|
||||
|
||||
|
||||
def local_context(context):
|
||||
return (type(context) is dict and set(context) == {"name", "endpoint"}
|
||||
and isinstance(context["name"], str) and re.fullmatch(r"[A-Za-z0-9_.-]+", context["name"])
|
||||
and isinstance(context["endpoint"], str) and context["endpoint"].startswith("unix:///")
|
||||
and not any(character in context["endpoint"] for character in "\r\n\0"))
|
||||
|
||||
|
||||
def container_command(root, output, bundle, run_id):
|
||||
require(all(path.is_absolute() and ":" not in str(path) for path in (root, output)), "Invalid Docker bind paths")
|
||||
require(local_context(bundle["dockerContext"]), "Expected the reviewed local Unix Docker context")
|
||||
return ["docker", "--host", bundle["dockerContext"]["endpoint"], "run", "--rm", "--init", "--pull", "never",
|
||||
"--network", "none", "--platform", "linux/arm64", "--read-only", "--workdir", "/task",
|
||||
"--name", f"opcua-late-slope-{run_id}",
|
||||
"--label", f"{DOCKER_LABEL}={run_id}", "-e", "OTOPCUA_SOAK_BUILD_SHA=" + bundle["sourceRevision"],
|
||||
"-v", f"{root / 'app'}:/app:ro", "-v", f"{root / 'tools'}:/tools:ro", "-v", f"{output}:/task",
|
||||
bundle["image"], "bash", "/tools/container.sh"]
|
||||
|
||||
|
||||
def digest(path):
|
||||
with path.open("rb") as stream:
|
||||
return hashlib.file_digest(stream, "sha256").hexdigest()
|
||||
|
||||
|
||||
def unique_object(pairs):
|
||||
result = {}
|
||||
for key, value in pairs:
|
||||
require(key not in result, f"Duplicate JSON key {key}")
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
def reject_constant(value):
|
||||
raise ValueError(f"Invalid JSON constant {value}")
|
||||
|
||||
|
||||
def json_object(text):
|
||||
value = json.loads(text, object_pairs_hook=unique_object, parse_constant=reject_constant)
|
||||
require(type(value) is dict, "Expected a JSON object")
|
||||
return value
|
||||
|
||||
|
||||
def read_object(path):
|
||||
return json_object(path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def read_rows(path):
|
||||
with path.open(encoding="utf-8") as stream:
|
||||
for line_number, line in enumerate(stream, 1):
|
||||
require(line.endswith("\n"), f"Truncated JSONL row {line_number}")
|
||||
try:
|
||||
yield json_object(line)
|
||||
except ValueError as error:
|
||||
raise ValueError(f"Invalid JSONL row {line_number}: {error}") from error
|
||||
|
||||
|
||||
def count(value, label, minimum=0):
|
||||
require(type(value) is int and minimum <= value <= (1 << 63) - 1, f"Invalid {label}")
|
||||
return value
|
||||
|
||||
|
||||
def seconds(value, label, minimum=0, maximum=CONTAINER_SECONDS):
|
||||
require(type(value) in (int, float) and minimum <= value <= maximum, f"Invalid {label}")
|
||||
return value
|
||||
|
||||
|
||||
def assertion_message(text):
|
||||
require(isinstance(text, str), "Missing original resource-cap assertion")
|
||||
message = text.replace("\r", "").split("\n at ", 1)[0].strip()
|
||||
normalized = re.sub(r"^Shouldly\.ShouldAssertException\s*:\s*", "Shouldly.ShouldAssertException: ", message)
|
||||
require(normalized.startswith("Shouldly.ShouldAssertException: ") and len(normalized) > 32,
|
||||
"The recorded failure is not a resource-cap assertion")
|
||||
return normalized
|
||||
|
||||
|
||||
def sample(row, cycle):
|
||||
value = row["resources"]
|
||||
require(type(value) is dict and set(value) == SAMPLE_FIELDS, f"Invalid sample fields at cycle {cycle}")
|
||||
require(count(value["Cycle"], "sample cycle", 1) == cycle, f"Out-of-order sample cycle {cycle}")
|
||||
seconds(value["Seconds"], "sample time", maximum=SECONDS + MAX_CYCLE_SECONDS)
|
||||
for field in SAMPLE_FIELDS - {"Cycle", "Seconds"}:
|
||||
count(value[field], field)
|
||||
require(all(value[field] == 0 for field in ZERO_FIELDS), f"Quiescent ownership failure at cycle {cycle}")
|
||||
return value
|
||||
|
||||
|
||||
def validate_rows(rows, revision):
|
||||
"""Validate the canonical row order, original budget and fixed-duration outcome."""
|
||||
rows = iter(rows)
|
||||
|
||||
def take(kind):
|
||||
row = next(rows, {})
|
||||
require(row.get("kind") == kind, f"Expected {kind}, found {row.get('kind')!r}")
|
||||
require(row.get("acceptance", False) is False and "satisfiesTwoHourDuration" not in row,
|
||||
"An ordinary acceptance result is forbidden")
|
||||
return row
|
||||
|
||||
start = take("start")
|
||||
require(start.get("mode") == MODE and start.get("requestedSeconds") == SECONDS
|
||||
and type(start["requestedSeconds"]) is int and start.get("minimumFullSeconds") == SECONDS
|
||||
and start.get("acceptance") is False, "Wrong fixed-duration diagnostic mode")
|
||||
require(start.get("build") == revision and re.fullmatch(r"[0-9a-f]{40}", revision), "Wrong source revision")
|
||||
require(start.get("runtime") == RUNTIME and start.get("architecture") == "Arm64" and start.get("sdk") == SDK,
|
||||
"Wrong Linux ARM64 runtime or SDK version")
|
||||
count(start.get("processId"), "test process ID", 1)
|
||||
seconds(start.get("startupSeconds"), "startup duration", maximum=SETTINGS["startupTimeoutSeconds"])
|
||||
limits = start.get("limits")
|
||||
require(type(limits) is dict and limits == BUDGETS and all(type(value) is int for value in limits.values()),
|
||||
"Original cold resource caps changed")
|
||||
|
||||
samples = []
|
||||
first_rejection = None
|
||||
completions = []
|
||||
# Buffer only a single row so the actual record order cannot be reconstructed by sorting.
|
||||
pending = next(rows, {})
|
||||
while pending.get("kind") == "active":
|
||||
cycle = len(samples) + 1
|
||||
require(count(pending.get("cycle"), "active cycle", 1) == cycle, "Missing or duplicate active cycle")
|
||||
active_counts = tuple(count(pending.get(field), field) for field in ("sessions", "subscriptions", "items"))
|
||||
require(active_counts == (2, 1, 3), f"Incomplete active session, subscription or item exercise at cycle {cycle}")
|
||||
for field in ("browsePoints", "historyPoints"):
|
||||
count(pending.get(field), field, 1)
|
||||
stall = take("network-stall-recovered")
|
||||
require(count(stall.get("cycle"), "recovered stall cycle", 1) == cycle, "Missing or duplicate recovered stall")
|
||||
seconds(stall.get("seconds"), "network stall time", maximum=MAX_CYCLE_SECONDS)
|
||||
require(isinstance(stall.get("status"), str) and stall["status"] in STALL_STATUSES,
|
||||
"Unexpected recovered network stall status")
|
||||
value = sample(take("resource-observation"), cycle)
|
||||
require(not samples or value["Seconds"] > samples[-1]["Seconds"], "Nonmonotonic or duplicate sample time")
|
||||
require(not completions or value["Seconds"] > completions[-1]["elapsedSeconds"],
|
||||
"Sample precedes completion of the previous cycle")
|
||||
samples.append(value)
|
||||
|
||||
if cycle >= 3:
|
||||
baseline = samples[2]
|
||||
require(all(value[field] == baseline[field] for field in STEADY_FIELDS),
|
||||
f"Quiescent model or certificate-store inventory changed at cycle {cycle}")
|
||||
exceeded = [field for field, cap in CAP_FIELDS if value[field] > baseline[field] + BUDGETS[cap]]
|
||||
if exceeded and first_rejection is None:
|
||||
rejection = take("budget-rejected")
|
||||
require(count(rejection.get("cycle"), "rejection cycle", 1) == cycle
|
||||
and sample(rejection, cycle) == value
|
||||
and sample({"resources": rejection.get("baseline")}, 3) == baseline,
|
||||
"First rejection does not match the failing sample and original cycle-three baseline")
|
||||
seconds(rejection.get("seconds"), "rejection time", minimum=value["Seconds"],
|
||||
maximum=SECONDS + MAX_CYCLE_SECONDS)
|
||||
first_rejection = {**rejection, "exceededFields": exceeded,
|
||||
"assertionMessage": assertion_message(rejection.get("failure"))}
|
||||
if cycle >= 26:
|
||||
retained = [row["ManagedBytes"] for row in samples[-24:]]
|
||||
require(not (all(a < b for a, b in zip(retained, retained[1:]))
|
||||
and retained[-1] - retained[0] > (16 << 20)),
|
||||
f"Managed growth guard failed at cycle {cycle}")
|
||||
|
||||
quiescent = take("quiescent-budget-rejected" if first_rejection else "quiescent")
|
||||
require(sample(quiescent, cycle) == value, "Quiescent sample differs from its pre-assertion observation")
|
||||
quiescent_seconds = seconds(quiescent.get("cycleSeconds"), "quiescent cycle duration", maximum=MAX_CYCLE_SECONDS)
|
||||
restart_seconds = 0
|
||||
if cycle % 4 == 0:
|
||||
restart = take("restart")
|
||||
require(count(restart.get("cycles"), "restart cycle", 1) == cycle
|
||||
and count(restart.get("restarts"), "restart count", 1) == cycle // 4, "Missing or duplicate active restart")
|
||||
bounded = seconds(restart.get("boundedRestartSeconds"), "bounded restart duration", maximum=RESTART_SECONDS)
|
||||
restart_seconds = seconds(restart.get("seconds"), "combined restart duration", minimum=bounded, maximum=MAX_CYCLE_SECONDS)
|
||||
completion = take("late-slope-cycle")
|
||||
require(count(completion.get("cycle"), "completed cycle", 1) == cycle
|
||||
and count(completion.get("restarts"), "completed restarts") == cycle // 4, "Invalid completed cycle ledger")
|
||||
elapsed = seconds(completion.get("elapsedSeconds"), "cycle completion time", minimum=value["Seconds"],
|
||||
maximum=SECONDS + MAX_CYCLE_SECONDS)
|
||||
seconds(completion.get("cycleSeconds"), "complete cycle duration", minimum=quiescent_seconds + restart_seconds,
|
||||
maximum=MAX_CYCLE_SECONDS)
|
||||
if first_rejection and first_rejection["cycle"] == cycle:
|
||||
require(first_rejection["seconds"] <= elapsed, "Rejection follows its completed cycle")
|
||||
require(not completions or completions[-1]["elapsedSeconds"] < SECONDS,
|
||||
"Another cycle began after the fixed duration")
|
||||
completions.append(completion)
|
||||
pending = next(rows, {})
|
||||
|
||||
result = pending
|
||||
require(result.get("kind") == "late-slope-result" and next(rows, None) is None,
|
||||
"Expected a unique final diagnostic result with no ordinary completion or trailing failure")
|
||||
require(result.get("mode") == MODE and result.get("acceptance") is False
|
||||
and "satisfiesTwoHourDuration" not in result and result.get("durationCompleted") is True
|
||||
and result.get("shutdownVerified") is True and result.get("fatalFailure") is False and result.get("failureTypes") == [],
|
||||
"Duration, shutdown or diagnostic outcome was incomplete")
|
||||
cycles = count(result.get("cycles"), "result cycles", 4)
|
||||
require(cycles == len(samples) and count(result.get("restarts"), "result restarts", 1) == cycles // 4,
|
||||
"Final cycle or restart count differs from the ledger")
|
||||
phase = seconds(result.get("cycleSeconds"), "canonical cycle phase", minimum=SECONDS, maximum=SECONDS + MAX_CYCLE_SECONDS)
|
||||
require(phase >= completions[-1]["elapsedSeconds"] and completions[-1]["elapsedSeconds"] >= SECONDS,
|
||||
"The final cycle does not cover the fixed duration")
|
||||
seconds(result.get("shutdownSeconds"), "shutdown duration", maximum=SHUTDOWN_SECONDS)
|
||||
require(result.get("coldBudgetRejected") is (first_rejection is not None), "The first cold-cap rejection was not preserved")
|
||||
return start, samples, completions, first_rejection, result
|
||||
|
||||
|
||||
def sample_summary(samples, fields):
|
||||
times = [value["Seconds"] for value in samples]
|
||||
summary = {"sampleCount": len(samples), "firstSeconds": times[0], "lastSeconds": times[-1],
|
||||
"spanSeconds": times[-1] - times[0], "maximumGapSeconds": max((b - a for a, b in zip(times, times[1:])), default=0)}
|
||||
for field in fields:
|
||||
values = [value[field] for value in samples]
|
||||
summary[field] = {"first": values[0], "last": values[-1], "min": min(values), "max": max(values), "median": median(values)}
|
||||
return summary
|
||||
|
||||
|
||||
def slope(samples, field):
|
||||
times = [value["Seconds"] for value in samples]
|
||||
mean = math.fsum(times) / len(times)
|
||||
mean_value = math.fsum(value[field] for value in samples) / len(samples)
|
||||
variance = math.fsum((time - mean) ** 2 for time in times)
|
||||
return 3600 * math.fsum((time - mean) * (value[field] - mean_value)
|
||||
for time, value in zip(times, samples)) / variance
|
||||
|
||||
|
||||
def describe(samples, completions):
|
||||
windows = []
|
||||
for begin, end in WINDOWS:
|
||||
subset = [value for value in samples if begin <= value["Seconds"] <= end]
|
||||
require(len(subset) >= 10, f"Insufficient observations in {begin}–{end} seconds")
|
||||
summary = sample_summary(subset, MEASUREMENTS)
|
||||
require(summary["firstSeconds"] <= begin + 60 and summary["lastSeconds"] >= end - 60
|
||||
and summary["spanSeconds"] >= 480 and summary["maximumGapSeconds"] <= 60,
|
||||
f"Incomplete coverage in {begin}–{end} seconds")
|
||||
windows.append({"windowSeconds": [begin, end], **summary})
|
||||
late = [value for value in samples if 1800 <= value["Seconds"] <= SECONDS]
|
||||
coverage = sample_summary(late, ())
|
||||
require(coverage["maximumGapSeconds"] <= 60, "An observation gap exceeds 60 seconds across the late phase")
|
||||
previous = [row for row in completions if row["elapsedSeconds"] <= 1800]
|
||||
cycles = len(previous)
|
||||
restarts = previous[-1]["restarts"] if previous else 0
|
||||
work = {"cycles": cycles, "restarts": restarts, "earlierSaturationWorkloadReached": cycles >= 385 and restarts >= 96}
|
||||
if not work["earlierSaturationWorkloadReached"]:
|
||||
work["interpretation"] = "Post-restart-step attribution withheld because the earlier workload counts fell short by 1800 seconds."
|
||||
return {
|
||||
"allQuiescent": sample_summary(samples, (*ZERO_FIELDS, *STEADY_FIELDS, *MEASUREMENTS)),
|
||||
"finalQuiescentSample": samples[-1],
|
||||
"windows": windows,
|
||||
"leastSquares": {**coverage, "rangeSeconds": [1800, SECONDS], "units": "bytes/hour",
|
||||
"rss": slope(late, "RssBytes"), "retainedManaged": slope(late, "ManagedBytes")},
|
||||
"workCompletedBy1800Seconds": work,
|
||||
}
|
||||
|
||||
|
||||
def check_trx(path, expected_names, failure=None):
|
||||
document = ET.parse(path).getroot()
|
||||
counters = document.findall("./t:ResultSummary/t:Counters", TRX)
|
||||
require(len(counters) == 1, f"Missing unique counters in {path.name}")
|
||||
counters = counters[0].attrib
|
||||
total = len(expected_names)
|
||||
failed = 1 if failure else 0
|
||||
expected = {"total": total, "executed": total, "passed": total - failed, "failed": failed,
|
||||
"error": 0, "timeout": 0, "aborted": 0, "notExecuted": 0}
|
||||
for key, value in expected.items():
|
||||
require(counters.get(key) == str(value), f"Unexpected {key} count in {path.name}")
|
||||
for key in ("inconclusive", "passedButRunAborted", "notRunnable", "disconnected", "inProgress", "pending"):
|
||||
require(counters.get(key, "0") == "0", f"Unexpected {key} count in {path.name}")
|
||||
results = document.findall("./t:Results/t:UnitTestResult", TRX)
|
||||
require(len(results) == total and {row.get("testName") for row in results} == expected_names,
|
||||
f"Wrong test identities in {path.name}")
|
||||
require(all(row.get("outcome") == ("Failed" if failure else "Passed") for row in results),
|
||||
f"Unexpected test outcome in {path.name}")
|
||||
if failure:
|
||||
actual = results[0].findtext("./t:Output/t:ErrorInfo/t:Message", namespaces=TRX)
|
||||
require(assertion_message(actual) == failure, "TRX failure differs from the first cold-cap assertion")
|
||||
return {"executed": total, "passed": total - failed, "failed": failed, "skipped": 0}
|
||||
|
||||
|
||||
def exit_status(path):
|
||||
value = path.read_text(encoding="ascii").strip()
|
||||
require(re.fullmatch(r"0|[1-9][0-9]{0,2}", value) and int(value) <= 255, f"Invalid {path.name}")
|
||||
return int(value)
|
||||
|
||||
|
||||
def inspect_run(path, provenance, wall_seconds):
|
||||
"""Check actual run evidence. This function neither launches Docker nor changes the evidence."""
|
||||
start, samples, completions, rejection, result = validate_rows(read_rows(path / "resources.jsonl"), provenance["sourceRevision"])
|
||||
wall = seconds(wall_seconds, "container wall time", minimum=SECONDS)
|
||||
require(start["startupSeconds"] + result["cycleSeconds"] + result["shutdownSeconds"] <= wall,
|
||||
"Startup, cycle and shutdown phases exceed measured wall time")
|
||||
test_exit = exit_status(path / "test-exit-status.txt")
|
||||
container_exit = exit_status(path / "container-exit-status.txt")
|
||||
require(test_exit == container_exit and ((test_exit != 0) == bool(rejection)), "Original test/container exit was not preserved")
|
||||
mapping = (path / "target-runtime.txt").read_text(encoding="ascii").splitlines()
|
||||
require(mapping == [f"targetPid={start['processId']}", f"actualExecutable=/app/{APP}",
|
||||
"mappedCoreClr=/app/libcoreclr.so", f"coreClrSha256={provenance['coreClrSha256']}"],
|
||||
"Published Linux apphost or mapped CLR was not verified for the recorded PID")
|
||||
controls = check_trx(path / "results/descriptor-controls.trx", DESCRIPTOR_TESTS)
|
||||
workload = check_trx(path / "results/late-slope.trx", {TEST_NAME}, rejection and rejection["assertionMessage"])
|
||||
return {"diagnosticOutcome": result, "firstColdRejection": rejection, "descriptorTests": controls,
|
||||
"experimentTests": workload, "testExitStatus": test_exit, "containerExitStatus": container_exit,
|
||||
**describe(samples, completions)}
|
||||
|
||||
|
||||
def evidence_hashes(path):
|
||||
result = {}
|
||||
for name in EVIDENCE_FILES:
|
||||
file = path / name
|
||||
require(file.is_file() and file.resolve() == file, f"Missing or linked evidence file {name}")
|
||||
result[name] = digest(file)
|
||||
return result
|
||||
|
||||
|
||||
def analyze_run(path, bundle_receipt_path, bundle_hash):
|
||||
require(re.fullmatch(r"[0-9a-f]{64}", bundle_hash) and digest(bundle_receipt_path) == bundle_hash,
|
||||
"Reviewed bundle receipt hash differs")
|
||||
bundle = read_object(bundle_receipt_path)
|
||||
require(bundle.get("kind") == "bundle" and all(type(bundle.get(key)) is type(value) and bundle[key] == value
|
||||
for key, value in SETTINGS.items()),
|
||||
"Invalid immutable bundle protocol")
|
||||
receipt = read_object(path / "run-receipt.json")
|
||||
provenance = read_object(path / "launch.json")
|
||||
require(receipt.get("kind") == "run" and provenance.get("kind") == "launch", "Wrong receipt types")
|
||||
for record in (receipt, provenance):
|
||||
require(record.get("protocol") == PROTOCOL and record.get("acceptance") is False
|
||||
and record.get("bundleReceiptSha256") == bundle_hash, "Wrong diagnostic provenance")
|
||||
for field in ("runId", "sourceRevision", "image", "coreClrSha256", "dockerContext", "command", "containerTimeoutSeconds"):
|
||||
require(receipt[field] == provenance[field], f"Launch and run receipts disagree on {field}")
|
||||
require(receipt["sourceRevision"] == bundle["sourceRevision"] and receipt["image"] == bundle["image"]
|
||||
and receipt["coreClrSha256"] == bundle["files"]["app/libcoreclr.so"]
|
||||
and receipt["dockerContext"] == bundle["dockerContext"],
|
||||
"Recorded source, image or runtime differs from the reviewed bundle")
|
||||
require(re.fullmatch(r"[0-9a-f]{32}", receipt["runId"])
|
||||
and re.fullmatch(r"sha256:[0-9a-f]{64}", receipt["image"])
|
||||
and re.fullmatch(r"[0-9a-f]{64}", receipt["coreClrSha256"]), "Invalid run identity or immutable provenance")
|
||||
require(receipt.get("diagnosticCompleted") is True and receipt.get("containerRemoved") is True,
|
||||
"The launcher did not verify duration, shutdown and container cleanup")
|
||||
require("validationErrors" not in receipt and provenance["containerTimeoutSeconds"] == CONTAINER_SECONDS
|
||||
and provenance["command"] == container_command(Path(provenance["bundlePath"]), Path(provenance["outputPath"]),
|
||||
bundle, receipt["runId"]), "The recorded container invocation differs")
|
||||
require(receipt.get("evidenceSha256") == evidence_hashes(path), "Recorded evidence hashes differ")
|
||||
report = inspect_run(path, provenance, receipt["wallSeconds"])
|
||||
for field in ("diagnosticOutcome", "testExitStatus", "containerExitStatus", "descriptorTests", "experimentTests"):
|
||||
require(receipt[field] == report[field], f"Run receipt differs from the raw {field}")
|
||||
require(receipt.get("launcherExitStatus") == report["testExitStatus"], "The launcher did not preserve the original exit")
|
||||
return {"protocol": PROTOCOL, "acceptance": False, "bundleReceiptSha256": bundle_hash,
|
||||
"sourceRevision": receipt["sourceRevision"], "evidenceSha256": receipt["evidenceSha256"], **report}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--run", type=Path, required=True)
|
||||
parser.add_argument("--bundle-receipt", type=Path, required=True)
|
||||
parser.add_argument("--bundle-receipt-sha256", required=True)
|
||||
options = parser.parse_args()
|
||||
try:
|
||||
print(json.dumps(analyze_run(options.run.resolve(strict=True), options.bundle_receipt,
|
||||
options.bundle_receipt_sha256), indent=2, allow_nan=False))
|
||||
except (OSError, ValueError, KeyError, TypeError, ET.ParseError) as error:
|
||||
print(f"Incomplete late-slope evidence: {error}", file=sys.stderr)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,129 +0,0 @@
|
||||
"""Checks shared by immutable artifact preparation and launch."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
from uuid import UUID
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from analyze import APP, RUNTIME, SETTINGS, digest, local_context, read_object, require
|
||||
|
||||
|
||||
TOOLS = ("analyze.py", "bundle.py", "launch.py", "container.sh", "README.md")
|
||||
TEST_DIRECTORY = f"tests/Server/{APP}"
|
||||
CANONICAL_SOURCES = tuple(f"{TEST_DIRECTORY}/{name}" for name in (
|
||||
"Sdk2LifecycleSoakTests.cs", "Sdk2LifecycleLateSlopeTests.cs", f"{APP}.csproj"))
|
||||
SDK_PACKAGES = {
|
||||
f"OPCFoundation.NetStandard.Opc.Ua.{component}/2.0.1"
|
||||
for component in ("Client", "Configuration", "Core", "Core.Schema", "Core.Types",
|
||||
"Security.Certificates", "Server", "Types")
|
||||
}
|
||||
GATEWAY_PACKAGES = {f"ZB.MOM.WW.HistorianGateway.{component}/1.0.0" for component in ("Client", "Contracts")}
|
||||
|
||||
|
||||
def context_identity(name):
|
||||
require(re.fullmatch(r"[A-Za-z0-9_.-]+", name), "Invalid local Docker context name")
|
||||
require(not any(os.environ.get(key) for key in ("DOCKER_HOST", "DOCKER_TLS", "DOCKER_TLS_VERIFY", "DOCKER_CERT_PATH"))
|
||||
and os.environ.get("DOCKER_CONTEXT", name) in ("", name), "Docker endpoint or TLS override is set")
|
||||
result = subprocess.check_output(["docker", "context", "inspect", name], text=True, timeout=15)
|
||||
contexts = json.loads(result)
|
||||
require(len(contexts) == 1 and contexts[0]["Name"] == name, "Expected one explicit Docker context")
|
||||
identity = {"name": name, "endpoint": contexts[0]["Endpoints"]["docker"]["Host"]}
|
||||
require(local_context(identity) and Path(identity["endpoint"][len("unix://"):]).is_socket(),
|
||||
"The reviewed Docker context must use a local Unix socket")
|
||||
return identity
|
||||
|
||||
|
||||
def image_identity(image, context):
|
||||
require(re.fullmatch(r"sha256:[0-9a-f]{64}", image), "Use a locally cached immutable image ID")
|
||||
result = subprocess.check_output(["docker", "--host", context["endpoint"], "image", "inspect", image], text=True, timeout=15)
|
||||
images = json.loads(result)
|
||||
require(len(images) == 1, "Expected one cached image")
|
||||
value = images[0]
|
||||
require((value["Id"], value["Os"], value["Architecture"]) == (image, "linux", "arm64"),
|
||||
"The immutable image must be Linux ARM64")
|
||||
return {"id": image, "os": "linux", "architecture": "arm64"}
|
||||
|
||||
|
||||
def manifest(root):
|
||||
"""Hash the exact regular-file tree and exclude only the receipt that contains it."""
|
||||
result = {}
|
||||
for path in sorted(root.rglob("*")):
|
||||
kind = path.lstat().st_mode
|
||||
require(stat.S_ISDIR(kind) or stat.S_ISREG(kind), f"Unsupported artifact type {path.relative_to(root)}")
|
||||
if stat.S_ISREG(kind) and path != root / "receipt.json":
|
||||
result[path.relative_to(root).as_posix()] = digest(path)
|
||||
return result
|
||||
|
||||
|
||||
def check_elf(path):
|
||||
with path.open("rb") as stream:
|
||||
header = stream.read(20)
|
||||
require(header[:6] == b"\x7fELF\x02\x01" and header[18:20] == b"\xb7\x00",
|
||||
f"{path.name} is not ELF64 AArch64")
|
||||
|
||||
|
||||
def check_application(app):
|
||||
check_elf(app / APP)
|
||||
require(os.access(app / APP, os.X_OK), "The Linux apphost is not executable")
|
||||
check_elf(app / "libcoreclr.so")
|
||||
options = read_object(app / f"{APP}.runtimeconfig.json")["runtimeOptions"]
|
||||
frameworks = options["includedFrameworks"]
|
||||
require(options["tfm"] == "net10.0" and "framework" not in options and "frameworks" not in options
|
||||
and isinstance(frameworks, list) and any(value["name"] == "Microsoft.NETCore.App" for value in frameworks)
|
||||
and all(value["version"] == RUNTIME for value in frameworks), "Wrong self-contained application runtime")
|
||||
dependencies = read_object(app / f"{APP}.deps.json")
|
||||
require(dependencies["runtimeTarget"]["name"] == ".NETCoreApp,Version=v10.0/linux-arm64", "Wrong application RID")
|
||||
libraries = dependencies["libraries"]
|
||||
sdk = {key for key in libraries if key.startswith("OPCFoundation.")}
|
||||
gateway = {key for key in libraries if key.startswith("ZB.MOM.WW.HistorianGateway.")}
|
||||
require(sdk == SDK_PACKAGES and gateway == GATEWAY_PACKAGES, "Expected exact SDK 2.0.1 and HistorianGateway 1.0.0 graph")
|
||||
return sorted(sdk), sorted(gateway)
|
||||
|
||||
|
||||
def check_modules(modules, files):
|
||||
require(isinstance(modules, list), "Missing managed module identities")
|
||||
seen = set()
|
||||
for module in modules:
|
||||
name = module["file"]
|
||||
require(name in files and name.startswith("app/") and name.endswith(".dll") and name not in seen,
|
||||
"Unexpected or duplicate managed module file")
|
||||
require(module["assembly"] and re.fullmatch(r"\d+(?:\.\d+){3}", module["version"])
|
||||
and UUID(module["mvid"]).int != 0, "Invalid assembly version or MVID")
|
||||
seen.add(name)
|
||||
required = {f"app/{APP}.dll", "app/Opc.Ua.Server.dll", "app/System.Private.CoreLib.dll",
|
||||
"app/ZB.MOM.WW.HistorianGateway.Client.dll", "app/ZB.MOM.WW.HistorianGateway.Contracts.dll"}
|
||||
require(required <= seen, "Missing application, runtime or dependency module identity")
|
||||
|
||||
|
||||
def verify_bundle(root, expected_hash):
|
||||
path = root / "receipt.json"
|
||||
require(path.is_file() and not path.is_symlink() and re.fullmatch(r"[0-9a-f]{64}", expected_hash)
|
||||
and digest(path) == expected_hash, "Reviewed bundle receipt hash differs")
|
||||
receipt = read_object(path)
|
||||
require(receipt.get("kind") == "bundle" and all(type(receipt.get(key)) is type(value) and receipt[key] == value
|
||||
for key, value in SETTINGS.items()), "Invalid fixed diagnostic settings")
|
||||
require(re.fullmatch(r"[0-9a-f]{40}", receipt["sourceRevision"]), "Invalid committed source revision")
|
||||
files = manifest(root)
|
||||
require(receipt["files"] == files, "The immutable bundle file set or a file hash changed")
|
||||
require({name for name in files if name.startswith("tools/")} == {f"tools/{name}" for name in TOOLS},
|
||||
"Unexpected bundled tools")
|
||||
sdk, gateway = check_application(root / "app")
|
||||
require(receipt["sdkLibraries"] == sdk and receipt["gatewayLibraries"] == gateway,
|
||||
"Dependency receipt differs from the published application")
|
||||
check_modules(receipt["managedModules"], files)
|
||||
require(receipt["imageIdentity"] == {"id": receipt["image"], "os": "linux", "architecture": "arm64"}
|
||||
and re.fullmatch(r"sha256:[0-9a-f]{64}", receipt["image"]), "Invalid immutable image identity")
|
||||
require(local_context(receipt["dockerContext"]), "Invalid reviewed local Docker context")
|
||||
require(receipt["sourceFiles"] and all(re.fullmatch(r"[0-9a-f]{64}", value) for value in receipt["sourceFiles"].values()),
|
||||
"Missing committed source hashes")
|
||||
require(set(CANONICAL_SOURCES) <= receipt["sourceFiles"].keys(), "Missing canonical test or project hash")
|
||||
for name in TOOLS:
|
||||
source = "scripts/validation/opcua-lifecycle-memory/late-slope/" + name
|
||||
require(receipt["sourceFiles"].get(source) == files[f"tools/{name}"], f"Bundled {name} differs from source")
|
||||
return receipt
|
||||
@@ -1,83 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Execute the immutable self-contained apphost through the cached Linux VSTest controller.
|
||||
verify_mapped_coreclr() {
|
||||
awk -v identity="$2" '
|
||||
$6 ~ /\/libcoreclr.so$/ {
|
||||
if (NF != 6 || ($5 " " $6) != identity) bad = 1
|
||||
else matched = 1
|
||||
}
|
||||
END { exit (matched && !bad) ? 0 : 1 }
|
||||
' "$1"
|
||||
}
|
||||
|
||||
# The offline controls source only the mapping check above.
|
||||
if [[ ${BASH_SOURCE[0]} != "$0" ]]; then return 0; fi
|
||||
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
app=ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests
|
||||
test_class="$app.Sdk2LifecycleSoakTests"
|
||||
mkdir -p /task/tmp /task/data /task/cli /task/results
|
||||
export TMPDIR=/task/tmp XDG_DATA_HOME=/task/data DOTNET_CLI_HOME=/task/cli
|
||||
export OTOPCUA_SDK2_SOAK=1 OTOPCUA_SDK2_SOAK_MODE=late-slope OTOPCUA_SDK2_SOAK_SECONDS=7200
|
||||
export OTOPCUA_SDK2_SOAK_OUTPUT=/task/resources.jsonl OPCUA_CERTIFICATE_LEAK_TRACKING=1
|
||||
export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1
|
||||
[[ $(uname -s) == Linux && $(uname -m) == aarch64 && -d /proc/self/fd ]]
|
||||
[[ ${OTOPCUA_SOAK_BUILD_SHA:-} =~ ^[0-9a-f]{40}$ ]]
|
||||
dotnet --info > /task/controller-runtime.txt
|
||||
|
||||
dotnet vstest "/app/$app.dll" \
|
||||
--TestCaseFilter:"FullyQualifiedName~$test_class.Descriptor_probe_" \
|
||||
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=descriptor-controls.trx' > /task/descriptor-controls.log 2>&1
|
||||
|
||||
# Verify actual execution before starting the long test. The host parses the complete TRX independently.
|
||||
controls=/task/results/descriptor-controls.trx
|
||||
counters=$(grep -E '^[[:space:]]*<Counters ' "$controls")
|
||||
[[ $(grep -Ec '^[[:space:]]*<Counters ' "$controls") == 1 ]]
|
||||
for attribute in total=2 executed=2 passed=2 failed=0 notExecuted=0 error=0 timeout=0 aborted=0; do
|
||||
[[ $counters == *" ${attribute%=*}=\"${attribute#*=}\""* ]]
|
||||
done
|
||||
[[ $(grep -Ec '^[[:space:]]*<UnitTestResult ' "$controls") == 2 ]]
|
||||
for name in Descriptor_probe_observes_an_open_PKI_file_through_a_symlink_alias_and_its_close \
|
||||
Descriptor_probe_times_out_and_reaps_a_process_that_keeps_both_streams_open; do
|
||||
result=$(grep -E '^[[:space:]]*<UnitTestResult ' "$controls" | grep -F "testName=\"$test_class.$name\"")
|
||||
[[ $result == *' outcome="Passed"'* && $result != *$'\n'* ]]
|
||||
done
|
||||
|
||||
vstest_pid=
|
||||
cleanup() {
|
||||
if [[ -n "$vstest_pid" ]]; then kill "$vstest_pid" 2>/dev/null || true; fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
dotnet vstest "/app/$app.dll" \
|
||||
--TestCaseFilter:"FullyQualifiedName=$test_class.Repeated_lifecycles_return_resources_to_a_steady_baseline" \
|
||||
--ResultsDirectory:/task/results '--Logger:trx;LogFileName=late-slope.trx' > /task/test.log 2>&1 &
|
||||
vstest_pid=$!
|
||||
|
||||
# The canonical startup deadline is 120 seconds. Allow controller startup before observing its first complete row.
|
||||
proof_deadline=$((SECONDS + 150))
|
||||
observed=0
|
||||
while ((SECONDS < proof_deadline)) && kill -0 "$vstest_pid" 2>/dev/null; do
|
||||
if [[ -s /task/resources.jsonl ]] && IFS= read -r header < /task/resources.jsonl; then
|
||||
[[ $header == *'"kind":"start"'* && $header == *'"mode":"late-slope"'* ]]
|
||||
pid=$(sed -n 's/.*"processId":\([1-9][0-9]*\),.*/\1/p' <<< "$header")
|
||||
[[ $pid =~ ^[1-9][0-9]*$ ]]
|
||||
executable=$(readlink "/proc/$pid/exe")
|
||||
[[ $executable == "/app/$app" ]]
|
||||
runtime=/app/libcoreclr.so
|
||||
verify_mapped_coreclr "/proc/$pid/maps" "$(stat -c '%i %n' "$runtime")"
|
||||
runtime_hash=$(sha256sum "$runtime")
|
||||
printf 'targetPid=%s\nactualExecutable=%s\nmappedCoreClr=%s\ncoreClrSha256=%s\n' \
|
||||
"$pid" "$executable" "$runtime" "${runtime_hash%% *}" > /task/target-runtime.txt
|
||||
observed=1
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
if [[ $observed != 1 ]]; then kill "$vstest_pid" 2>/dev/null || true; fi
|
||||
test_status=0
|
||||
wait "$vstest_pid" || test_status=$?
|
||||
vstest_pid=
|
||||
printf '%s\n' "$test_status" > /task/test-exit-status.txt
|
||||
if [[ $test_status != 0 ]]; then exit "$test_status"; fi
|
||||
[[ $observed == 1 ]]
|
||||
@@ -1,130 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify an immutable bundle or launch its fixed-duration Linux diagnostic."""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import uuid
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from analyze import CONTAINER_SECONDS, DOCKER_LABEL, PROTOCOL, container_command, evidence_hashes, inspect_run, require
|
||||
from bundle import context_identity, image_identity, verify_bundle
|
||||
|
||||
|
||||
def remove_container(context, run_id):
|
||||
docker = ["docker", "--host", context["endpoint"]]
|
||||
|
||||
def containers():
|
||||
result = subprocess.check_output([*docker, "ps", "--all", "--quiet", "--no-trunc",
|
||||
"--filter", f"label={DOCKER_LABEL}={run_id}"], text=True, timeout=10)
|
||||
ids = result.split()
|
||||
require(all(re.fullmatch(r"[0-9a-f]{64}", value) for value in ids), "Unexpected container ID")
|
||||
return ids
|
||||
|
||||
ids = containers()
|
||||
if ids:
|
||||
subprocess.run([*docker, "rm", "--force", *ids], stdout=subprocess.DEVNULL,
|
||||
stderr=subprocess.DEVNULL, timeout=15)
|
||||
require(not containers(), "The task-owned container is still present")
|
||||
|
||||
|
||||
def write(path, value):
|
||||
with path.open("x", encoding="utf-8") as stream:
|
||||
json.dump(value, stream, indent=2, allow_nan=False)
|
||||
stream.write("\n")
|
||||
|
||||
|
||||
def verify_local_image(bundle):
|
||||
context = bundle["dockerContext"]
|
||||
require(context_identity(context["name"]) == context, "Reviewed Docker context endpoint changed")
|
||||
require(image_identity(bundle["image"], context) == bundle["imageIdentity"], "Wrong cached image identity")
|
||||
|
||||
|
||||
def launch(root, bundle, bundle_hash, output):
|
||||
require(Path(__file__).resolve() == root / "tools/launch.py", "Invoke the reviewed bundled launcher")
|
||||
require(not output.is_relative_to(root), "Run output must be outside the immutable bundle")
|
||||
run_id = uuid.uuid4().hex
|
||||
invocation = container_command(root, output, bundle, run_id)
|
||||
output.mkdir(mode=0o700, parents=True, exist_ok=False)
|
||||
provenance = {"kind": "launch", "protocol": PROTOCOL, "acceptance": False, "runId": run_id,
|
||||
"bundleReceiptSha256": bundle_hash, "sourceRevision": bundle["sourceRevision"], "image": bundle["image"],
|
||||
"coreClrSha256": bundle["files"]["app/libcoreclr.so"], "command": invocation,
|
||||
"dockerContext": bundle["dockerContext"], "bundlePath": str(root), "outputPath": str(output),
|
||||
"containerTimeoutSeconds": CONTAINER_SECONDS}
|
||||
write(output / "launch.json", provenance)
|
||||
errors = []
|
||||
removed = False
|
||||
started = time.monotonic()
|
||||
try:
|
||||
with (output / "container.log").open("x", encoding="utf-8") as log:
|
||||
process = subprocess.run(invocation, stdout=log, stderr=subprocess.STDOUT, timeout=CONTAINER_SECONDS)
|
||||
status = process.returncode
|
||||
except subprocess.TimeoutExpired:
|
||||
status = 124
|
||||
errors.append("The container reached the fixed outer deadline")
|
||||
except KeyboardInterrupt:
|
||||
status = 130
|
||||
errors.append("Container execution was interrupted")
|
||||
except OSError as error:
|
||||
status = 125
|
||||
errors.append(str(error))
|
||||
finally:
|
||||
wall = time.monotonic() - started
|
||||
try:
|
||||
remove_container(bundle["dockerContext"], run_id)
|
||||
removed = True
|
||||
except (OSError, subprocess.SubprocessError, ValueError) as error:
|
||||
errors.append(f"Container cleanup failed: {error}")
|
||||
(output / "container-exit-status.txt").write_text(f"{status}\n", encoding="ascii")
|
||||
receipt = {**provenance, "kind": "run", "containerExitStatus": status, "wallSeconds": wall,
|
||||
"containerRemoved": removed, "diagnosticCompleted": False}
|
||||
try:
|
||||
verify_bundle(root, bundle_hash)
|
||||
verify_local_image(bundle)
|
||||
receipt["evidenceSha256"] = evidence_hashes(output)
|
||||
inspected = inspect_run(output, provenance, wall)
|
||||
for field in ("diagnosticOutcome", "testExitStatus", "descriptorTests", "experimentTests"):
|
||||
receipt[field] = inspected[field]
|
||||
except (OSError, KeyError, TypeError, ValueError, ET.ParseError, subprocess.SubprocessError) as error:
|
||||
errors.append(f"Evidence validation failed: {error}")
|
||||
receipt["diagnosticCompleted"] = not errors
|
||||
if errors:
|
||||
receipt["validationErrors"] = errors
|
||||
# Return the original container status when the test rethrows its first resource cap.
|
||||
receipt["launcherExitStatus"] = (128 - status if status < 0 else status) or int(bool(errors))
|
||||
write(output / "run-receipt.json", receipt)
|
||||
print(json.dumps(receipt, indent=2, allow_nan=False))
|
||||
return receipt["launcherExitStatus"]
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--bundle", type=Path, required=True)
|
||||
parser.add_argument("--receipt-sha256", required=True)
|
||||
action = parser.add_mutually_exclusive_group(required=True)
|
||||
action.add_argument("--verify-only", action="store_true")
|
||||
action.add_argument("--output", type=Path)
|
||||
options = parser.parse_args()
|
||||
try:
|
||||
root = options.bundle.resolve(strict=True)
|
||||
bundle = verify_bundle(root, options.receipt_sha256)
|
||||
verify_local_image(bundle)
|
||||
if options.verify_only:
|
||||
print(json.dumps({"protocol": PROTOCOL, "sourceRevision": bundle["sourceRevision"],
|
||||
"receiptSha256": options.receipt_sha256, "verified": True,
|
||||
"acceptance": False, "workloadLaunched": False}, indent=2))
|
||||
return 0
|
||||
return launch(root, bundle, options.receipt_sha256, options.output.resolve())
|
||||
except (OSError, KeyError, TypeError, ValueError, subprocess.SubprocessError) as error:
|
||||
print(f"Late-slope launcher rejected the request: {error}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
@@ -1,97 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Publish and record a fresh immutable Linux ARM64 bundle without running the workload."""
|
||||
|
||||
import argparse
|
||||
from datetime import datetime, timezone
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from analyze import APP, RUNTIME, SETTINGS, digest, require
|
||||
from bundle import CANONICAL_SOURCES, TOOLS, check_application, context_identity, image_identity, manifest, verify_bundle
|
||||
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
REPO = HERE.parents[3]
|
||||
PROJECT = REPO / "tests/Server" / APP / (APP + ".csproj")
|
||||
SUPPORT = PROJECT.with_name("Sdk2LifecycleLateSlopeTests.cs")
|
||||
MODULE_SOURCE = HERE.parent / "ArtifactModuleInfo.cs"
|
||||
DESIGN = HERE.parent / "LATE_SLOPE.md"
|
||||
|
||||
|
||||
def check_source(revision):
|
||||
current = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=REPO, text=True).strip()
|
||||
require(revision == current, "Publish the specified committed source revision")
|
||||
require(not subprocess.check_output(["git", "status", "--porcelain"], cwd=REPO, text=True).strip(),
|
||||
"The publication checkout must be clean")
|
||||
require('"late-slope-result"' in SUPPORT.read_text(encoding="utf-8"), "The committed canonical test lacks late-slope mode")
|
||||
sources = [*(REPO / name for name in CANONICAL_SOURCES), MODULE_SOURCE, DESIGN,
|
||||
HERE / "prepare.py", HERE / "test_offline.py", *(HERE / name for name in TOOLS)]
|
||||
return {path.relative_to(REPO).as_posix(): digest(path) for path in sources}
|
||||
|
||||
|
||||
def managed_modules(build, root):
|
||||
project = ET.Element("Project", Sdk="Microsoft.NET.Sdk")
|
||||
settings = ET.SubElement(project, "PropertyGroup")
|
||||
for key, value in {"OutputType": "Exe", "TargetFramework": "net10.0", "ImplicitUsings": "enable",
|
||||
"EnableDefaultCompileItems": "false", "TreatWarningsAsErrors": "true"}.items():
|
||||
ET.SubElement(settings, key).text = value
|
||||
ET.SubElement(ET.SubElement(project, "ItemGroup"), "Compile", Include=str(MODULE_SOURCE))
|
||||
path = build / "module-info.csproj"
|
||||
ET.ElementTree(project).write(path, encoding="unicode")
|
||||
with (root / "module-info-build.log").open("w", encoding="utf-8") as log:
|
||||
subprocess.run(["dotnet", "build", str(path), "-c", "Release", "-m:2", "--nologo"],
|
||||
stdout=log, stderr=subprocess.STDOUT, check=True, timeout=300)
|
||||
command = ["dotnet", str(build / "bin/Release/net10.0/module-info.dll"), str(root), str(root / "app")]
|
||||
return json.loads(subprocess.check_output(command, text=True, timeout=60))
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--output", type=Path, required=True)
|
||||
parser.add_argument("--source-revision", required=True)
|
||||
parser.add_argument("--image", required=True)
|
||||
parser.add_argument("--docker-context", required=True)
|
||||
options = parser.parse_args()
|
||||
sources = check_source(options.source_revision)
|
||||
context = context_identity(options.docker_context)
|
||||
image = image_identity(options.image, context)
|
||||
root = options.output.resolve()
|
||||
root.mkdir(mode=0o700, parents=True, exist_ok=False)
|
||||
with tempfile.TemporaryDirectory(prefix="opcua-late-slope-publish-") as scratch:
|
||||
build = Path(scratch)
|
||||
command = ["dotnet", "publish", str(PROJECT), "-c", "Release", "-r", "linux-arm64",
|
||||
"--self-contained", "true", f"-p:RuntimeFrameworkVersion={RUNTIME}",
|
||||
"-p:PublishSingleFile=false", "-p:PublishTrimmed=false", "-p:UseAppHost=true",
|
||||
"--artifacts-path", str(build / "artifacts"), "-o", str(root / "app"), "-m:2", "--nologo"]
|
||||
with (root / "publish.log").open("w", encoding="utf-8") as log:
|
||||
subprocess.run(command, cwd=REPO, stdout=log, stderr=subprocess.STDOUT, check=True, timeout=900)
|
||||
sdk, gateway = check_application(root / "app")
|
||||
modules = managed_modules(build, root)
|
||||
tools = root / "tools"
|
||||
tools.mkdir()
|
||||
for name in TOOLS:
|
||||
shutil.copy2(HERE / name, tools / name)
|
||||
require(check_source(options.source_revision) == sources, "Committed inputs changed during publication")
|
||||
require(context_identity(options.docker_context) == context and image_identity(options.image, context) == image,
|
||||
"The local Docker context or image changed during publication")
|
||||
receipt = {**SETTINGS, "kind": "bundle", "sourceRevision": options.source_revision, "sourceFiles": sources, "dockerContext": context,
|
||||
"image": options.image, "imageIdentity": image, "preparedUtc": datetime.now(timezone.utc).isoformat(),
|
||||
"publishCommand": command, "sdkLibraries": sdk, "gatewayLibraries": gateway,
|
||||
"managedModules": modules, "files": manifest(root)}
|
||||
path = root / "receipt.json"
|
||||
path.write_text(json.dumps(receipt, indent=2, allow_nan=False) + "\n", encoding="utf-8")
|
||||
sha = digest(path)
|
||||
verify_bundle(root, sha)
|
||||
print(json.dumps({"bundle": str(root), "sourceRevision": options.source_revision,
|
||||
"receiptSha256": sha, "acceptance": False, "workloadLaunched": False}, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,383 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Synthetic evidence controls. No application, Docker, or workload execution."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
from uuid import UUID
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
import analyze
|
||||
import bundle
|
||||
|
||||
|
||||
REVISION = "a" * 40
|
||||
IMAGE = "sha256:" + "b" * 64
|
||||
CONTEXT = {"name": "local-control", "endpoint": "unix:///tmp/control.sock"}
|
||||
RUN_ID = "c" * 32
|
||||
|
||||
|
||||
def canonical_rows(period=4, rejected=True):
|
||||
yield {"kind": "start", "mode": analyze.MODE, "requestedSeconds": 7200, "minimumFullSeconds": 7200,
|
||||
"runtime": analyze.RUNTIME, "sdk": analyze.SDK, "architecture": "Arm64", "processId": 123,
|
||||
"startupSeconds": 1, "build": REVISION, "acceptance": False, "limits": analyze.BUDGETS.copy()}
|
||||
cycles = 7200 // period
|
||||
baseline = None
|
||||
for cycle in range(1, cycles + 1):
|
||||
elapsed = cycle * period - 1
|
||||
value = dict.fromkeys(analyze.SAMPLE_FIELDS, 0)
|
||||
value.update(Cycle=cycle, Seconds=elapsed, Variables=19, Folders=4, Conditions=1,
|
||||
CachedCertificateStores=2, Descriptors=190, ManagedBytes=20_000_000 + elapsed * 32,
|
||||
RssBytes=200_000_000 + elapsed * 128, GcCommittedBytes=48_000_000, JitMethods=76000,
|
||||
JitIlBytes=11500000, ActiveTimers=12, Threads=24)
|
||||
if cycle == 3:
|
||||
baseline = value.copy()
|
||||
if rejected and cycle == 4:
|
||||
limit = baseline["RssBytes"] + analyze.BUDGETS["rssGrowthBytes"]
|
||||
value["RssBytes"] = limit + 1
|
||||
yield {"kind": "active", "cycle": cycle, "sessions": 2, "subscriptions": 1, "items": 3,
|
||||
"browsePoints": 1, "historyPoints": 6}
|
||||
yield {"kind": "network-stall-recovered", "cycle": cycle, "status": "BadRequestInterrupted", "seconds": 1}
|
||||
yield {"kind": "resource-observation", "resources": value.copy()}
|
||||
if rejected and cycle == 4:
|
||||
yield {"kind": "budget-rejected", "cycle": cycle, "seconds": elapsed + 0.1,
|
||||
"resources": value.copy(), "baseline": baseline,
|
||||
"failure": (f"Shouldly.ShouldAssertException: {limit + 1}L\r\n should be less than or equal to"
|
||||
f"\r\n{limit}L\r\n but was not\n at synthetic fixture")}
|
||||
yield {"kind": "quiescent-budget-rejected" if rejected and cycle >= 4 else "quiescent",
|
||||
"cycleSeconds": period - 1, "resources": value.copy()}
|
||||
if cycle % 4 == 0:
|
||||
yield {"kind": "restart", "cycles": cycle, "restarts": cycle // 4, "seconds": 1, "boundedRestartSeconds": 0.9}
|
||||
yield {"kind": "late-slope-cycle", "cycle": cycle, "restarts": cycle // 4,
|
||||
"elapsedSeconds": cycle * period, "cycleSeconds": period}
|
||||
yield {"kind": "late-slope-result", "mode": analyze.MODE, "cycles": cycles, "restarts": cycles // 4,
|
||||
"cycleSeconds": cycles * period, "shutdownSeconds": 2, "durationCompleted": True,
|
||||
"shutdownVerified": True, "fatalFailure": False, "failureTypes": [], "coldBudgetRejected": rejected, "acceptance": False}
|
||||
|
||||
|
||||
def write_json(path, value):
|
||||
path.write_text(json.dumps(value) + "\n", encoding="utf-8")
|
||||
|
||||
|
||||
def write_trx(path, names, failure=None):
|
||||
root = ET.Element("TestRun", xmlns=analyze.TRX["t"])
|
||||
results = ET.SubElement(root, "Results")
|
||||
for name in sorted(names):
|
||||
result = ET.SubElement(results, "UnitTestResult", testName=name, outcome="Failed" if failure else "Passed")
|
||||
if failure:
|
||||
output = ET.SubElement(result, "Output")
|
||||
ET.SubElement(ET.SubElement(output, "ErrorInfo"), "Message").text = failure
|
||||
total = len(names)
|
||||
summary = ET.SubElement(root, "ResultSummary")
|
||||
ET.SubElement(summary, "Counters", total=str(total), executed=str(total), passed=str(total - bool(failure)),
|
||||
failed=str(int(bool(failure))), notExecuted="0", error="0", timeout="0", aborted="0")
|
||||
ET.ElementTree(root).write(path, encoding="utf-8")
|
||||
|
||||
|
||||
class RowControls(unittest.TestCase):
|
||||
def test_fixed_windows_and_known_linear_slopes(self):
|
||||
_, samples, completions, rejection, _ = analyze.validate_rows(canonical_rows(), REVISION)
|
||||
report = analyze.describe(samples, completions)
|
||||
self.assertEqual(rejection["cycle"], 4)
|
||||
self.assertEqual(report["allQuiescent"]["sampleCount"], 1800)
|
||||
self.assertEqual(report["allQuiescent"]["RssBytes"]["max"], rejection["resources"]["RssBytes"])
|
||||
self.assertEqual([row["windowSeconds"] for row in report["windows"]], [[1800, 2400], [3600, 4200], [6600, 7200]])
|
||||
self.assertEqual([row["sampleCount"] for row in report["windows"]], [150, 150, 150])
|
||||
self.assertAlmostEqual(report["leastSquares"]["rss"], 128 * 3600)
|
||||
self.assertAlmostEqual(report["leastSquares"]["retainedManaged"], 32 * 3600)
|
||||
self.assertEqual(report["leastSquares"]["sampleCount"], 1350)
|
||||
self.assertTrue(report["workCompletedBy1800Seconds"]["earlierSaturationWorkloadReached"])
|
||||
|
||||
def test_slopes_remain_descriptive_below_earlier_workload(self):
|
||||
_, samples, completions, rejection, _ = analyze.validate_rows(canonical_rows(25, rejected=False), REVISION)
|
||||
report = analyze.describe(samples, completions)
|
||||
self.assertIsNone(rejection)
|
||||
work = report["workCompletedBy1800Seconds"]
|
||||
self.assertEqual((work["cycles"], work["restarts"]), (72, 18))
|
||||
self.assertFalse(work["earlierSaturationWorkloadReached"])
|
||||
self.assertIn("attribution withheld", work["interpretation"])
|
||||
self.assertAlmostEqual(report["leastSquares"]["rss"], 128 * 3600)
|
||||
|
||||
def test_wrong_mode_duration_runtime_or_startup_are_rejected(self):
|
||||
for field, value in (("mode", "full"), ("requestedSeconds", 90), ("runtime", "10.0.3"),
|
||||
("architecture", "X64"), ("sdk", "2.0.0"), ("startupSeconds", 121), ("acceptance", True)):
|
||||
with self.subTest(field=field):
|
||||
rows = list(canonical_rows(25))
|
||||
rows[0][field] = value
|
||||
with self.assertRaises(ValueError):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
|
||||
def test_wrong_final_state_never_yields_a_report(self):
|
||||
for field, value in (("kind", "complete"), ("cycleSeconds", 7199.9), ("cycleSeconds", 7231),
|
||||
("shutdownVerified", False), ("durationCompleted", False), ("fatalFailure", True),
|
||||
("shutdownSeconds", 61), ("coldBudgetRejected", False), ("acceptance", True), ("restarts", 1)):
|
||||
with self.subTest(field=field, value=value):
|
||||
rows = list(canonical_rows(25))
|
||||
rows[-1][field] = value
|
||||
with self.assertRaises(ValueError):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
|
||||
def test_duplicate_reordered_missing_or_malformed_samples(self):
|
||||
def change(rows, position, field, value):
|
||||
rows[position]["resources"][field] = value
|
||||
|
||||
edits = (
|
||||
lambda rows: rows.insert(4, rows[3]),
|
||||
lambda rows: rows.pop(3),
|
||||
lambda rows: change(rows, 8, "Cycle", 1),
|
||||
lambda rows: change(rows, 8, "Seconds", rows[3]["resources"]["Seconds"]),
|
||||
lambda rows: change(rows, 3, "RssBytes", -1),
|
||||
lambda rows: change(rows, 3, "ManagedBytes", float("inf")),
|
||||
lambda rows: change(rows, 3, "PkiDescriptors", 1),
|
||||
lambda rows: rows.append({"kind": "complete"}),
|
||||
)
|
||||
for edit in edits:
|
||||
rows = list(canonical_rows(25))
|
||||
edit(rows)
|
||||
with self.assertRaises(ValueError):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
|
||||
def test_first_rejection_cannot_disappear_or_change_baseline(self):
|
||||
rows = list(canonical_rows(25))
|
||||
first = next(i for i, row in enumerate(rows) if row["kind"] == "budget-rejected")
|
||||
rows[first]["baseline"]["RssBytes"] -= 1
|
||||
with self.assertRaisesRegex(ValueError, "baseline"):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
rows = list(canonical_rows(25))
|
||||
later = next(row for row in rows if row["kind"] == "quiescent-budget-rejected" and row["resources"]["Cycle"] == 5)
|
||||
later["kind"] = "quiescent"
|
||||
with self.assertRaisesRegex(ValueError, "quiescent-budget-rejected"):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
rows = list(canonical_rows(25))
|
||||
rows.pop(first)
|
||||
with self.assertRaisesRegex(ValueError, "budget-rejected"):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
|
||||
def test_bounded_restart_and_complete_cycle_durations(self):
|
||||
for kind, field, value, expected in (
|
||||
("restart", "boundedRestartSeconds", 25.1, "bounded restart duration"),
|
||||
("restart", "seconds", 31, "combined restart duration"),
|
||||
("late-slope-cycle", "cycleSeconds", 31, "complete cycle duration"),
|
||||
):
|
||||
with self.subTest(field=field):
|
||||
rows = list(canonical_rows(25))
|
||||
row = next(row for row in rows if row["kind"] == kind)
|
||||
row[field] = value
|
||||
with self.assertRaisesRegex(ValueError, expected):
|
||||
analyze.validate_rows(rows, REVISION)
|
||||
|
||||
def test_missing_windows_edges_and_internal_or_between_window_gaps(self):
|
||||
_, samples, completions, _, _ = analyze.validate_rows(canonical_rows(25), REVISION)
|
||||
for begin, end in ((3600, 4200), (1800, 1880), (7110, 7200), (1900, 1980), (2900, 2980)):
|
||||
with self.subTest(begin=begin, end=end):
|
||||
incomplete = [sample for sample in samples if not begin <= sample["Seconds"] <= end]
|
||||
with self.assertRaises(ValueError):
|
||||
analyze.describe(incomplete, completions)
|
||||
|
||||
def test_jsonl_rejects_duplicate_keys_nonfinite_literals_and_truncation(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
path = Path(temporary) / "samples.jsonl"
|
||||
for content in ('{"kind":"start","kind":"complete"}\n', '{"seconds":NaN}\n', '{"kind":"start"}'):
|
||||
path.write_text(content, encoding="utf-8")
|
||||
with self.assertRaises(ValueError):
|
||||
list(analyze.read_rows(path))
|
||||
|
||||
|
||||
class ReceiptControls(unittest.TestCase):
|
||||
def setUp(self):
|
||||
temporary = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(temporary.cleanup)
|
||||
self.root = Path(temporary.name).resolve()
|
||||
self.run = self.root / "run"
|
||||
self.bundle_receipt = self.root / "bundle.json"
|
||||
(self.run / "results").mkdir(parents=True)
|
||||
self.build_evidence()
|
||||
|
||||
def build_evidence(self, rejected=True):
|
||||
self.bundle = {**analyze.SETTINGS, "kind": "bundle", "sourceRevision": REVISION, "image": IMAGE,
|
||||
"dockerContext": CONTEXT, "files": {"app/libcoreclr.so": "d" * 64}}
|
||||
write_json(self.bundle_receipt, self.bundle)
|
||||
self.bundle_hash = analyze.digest(self.bundle_receipt)
|
||||
self.provenance = {"kind": "launch", "protocol": analyze.PROTOCOL, "acceptance": False,
|
||||
"sourceRevision": REVISION, "image": IMAGE, "dockerContext": CONTEXT, "runId": RUN_ID,
|
||||
"bundleReceiptSha256": self.bundle_hash, "coreClrSha256": "d" * 64,
|
||||
"containerTimeoutSeconds": 7440, "bundlePath": str(self.root / "bundle"), "outputPath": str(self.run)}
|
||||
self.provenance["command"] = analyze.container_command(self.root / "bundle", self.run, self.bundle, RUN_ID)
|
||||
write_json(self.run / "launch.json", self.provenance)
|
||||
rows = list(canonical_rows(25, rejected))
|
||||
(self.run / "resources.jsonl").write_text("".join(json.dumps(row) + "\n" for row in rows), encoding="utf-8")
|
||||
status = int(rejected)
|
||||
for filename in ("test-exit-status.txt", "container-exit-status.txt"):
|
||||
(self.run / filename).write_text(f"{status}\n", encoding="ascii")
|
||||
(self.run / "target-runtime.txt").write_text(
|
||||
f"targetPid=123\nactualExecutable=/app/{analyze.APP}\nmappedCoreClr=/app/libcoreclr.so\ncoreClrSha256={'d' * 64}\n",
|
||||
encoding="ascii")
|
||||
for filename in ("container.log", "controller-runtime.txt", "descriptor-controls.log", "test.log"):
|
||||
(self.run / filename).write_text("Synthetic control fixture\n", encoding="utf-8")
|
||||
write_trx(self.run / "results/descriptor-controls.trx", analyze.DESCRIPTOR_TESTS)
|
||||
failure = next((row["failure"] for row in rows if row["kind"] == "budget-rejected"), None)
|
||||
message = analyze.assertion_message(failure).replace("Exception:", "Exception :", 1) if failure else None
|
||||
write_trx(self.run / "results/late-slope.trx", {analyze.TEST_NAME}, message)
|
||||
actual = analyze.inspect_run(self.run, self.provenance, 7205)
|
||||
self.receipt = {**self.provenance, "kind": "run", "diagnosticCompleted": True, "containerRemoved": True,
|
||||
"wallSeconds": 7205, "launcherExitStatus": status, **{key: actual[key] for key in (
|
||||
"testExitStatus", "containerExitStatus", "descriptorTests", "experimentTests", "diagnosticOutcome")}}
|
||||
self.refresh_receipt()
|
||||
|
||||
def refresh_receipt(self):
|
||||
self.receipt["evidenceSha256"] = analyze.evidence_hashes(self.run)
|
||||
write_json(self.run / "run-receipt.json", self.receipt)
|
||||
|
||||
def report(self):
|
||||
return analyze.analyze_run(self.run, self.bundle_receipt, self.bundle_hash)
|
||||
|
||||
def test_cold_failure_and_zero_exit_are_separate_diagnostic_results(self):
|
||||
cold = self.report()
|
||||
self.assertEqual(cold["testExitStatus"], 1)
|
||||
self.assertFalse(cold["acceptance"])
|
||||
self.assertEqual(cold["firstColdRejection"]["exceededFields"], ["RssBytes"])
|
||||
self.build_evidence(rejected=False)
|
||||
within_cap = self.report()
|
||||
self.assertEqual(within_cap["testExitStatus"], 0)
|
||||
self.assertFalse(within_cap["acceptance"])
|
||||
self.assertIsNone(within_cap["firstColdRejection"])
|
||||
|
||||
def test_changed_hash_or_bad_run_receipt_rejected(self):
|
||||
(self.run / "test.log").write_text("Changed evidence\n", encoding="utf-8")
|
||||
with self.assertRaisesRegex(ValueError, "evidence hashes"):
|
||||
self.report()
|
||||
for key, value in (("launcherExitStatus", 0), ("containerRemoved", False), ("diagnosticCompleted", False),
|
||||
("wallSeconds", 7441), ("bundleReceiptSha256", "f" * 64)):
|
||||
with self.subTest(key=key):
|
||||
self.build_evidence()
|
||||
self.receipt[key] = value
|
||||
self.refresh_receipt()
|
||||
with self.assertRaises(ValueError):
|
||||
self.report()
|
||||
|
||||
def test_rehashed_exit_runtime_and_trx_cannot_mask_incomplete_evidence(self):
|
||||
for filename, contents, pattern in (
|
||||
("test-exit-status.txt", "0\n", "test/container exit"),
|
||||
("target-runtime.txt", "targetPid=122\n", "mapped CLR"),
|
||||
):
|
||||
with self.subTest(filename=filename):
|
||||
self.build_evidence()
|
||||
(self.run / filename).write_text(contents, encoding="ascii")
|
||||
self.refresh_receipt()
|
||||
with self.assertRaisesRegex(ValueError, pattern):
|
||||
self.report()
|
||||
self.build_evidence()
|
||||
write_trx(self.run / "results/late-slope.trx", {analyze.TEST_NAME}, "Shouldly.ShouldAssertException: wrong assertion")
|
||||
self.refresh_receipt()
|
||||
with self.assertRaisesRegex(ValueError, "first cold-cap assertion"):
|
||||
self.report()
|
||||
write_trx(self.run / "results/descriptor-controls.trx", {"SkippedOrWrongControl"})
|
||||
self.refresh_receipt()
|
||||
with self.assertRaisesRegex(ValueError, "descriptor-controls.trx"):
|
||||
self.report()
|
||||
|
||||
def test_recorded_command_must_use_the_same_local_isolation(self):
|
||||
for isolation in ("network", "read-only rootfs"):
|
||||
with self.subTest(isolation=isolation):
|
||||
self.build_evidence()
|
||||
invocation = self.provenance["command"].copy()
|
||||
if isolation == "network":
|
||||
invocation[invocation.index("--network") + 1] = "host"
|
||||
else:
|
||||
invocation.remove("--read-only")
|
||||
self.provenance["command"] = self.receipt["command"] = invocation
|
||||
write_json(self.run / "launch.json", self.provenance)
|
||||
self.refresh_receipt()
|
||||
with self.assertRaisesRegex(ValueError, "container invocation"):
|
||||
self.report()
|
||||
|
||||
|
||||
class BundleControls(unittest.TestCase):
|
||||
def test_mapped_runtime_requires_the_mounted_inode_and_live_file(self):
|
||||
script = Path(__file__).with_name("container.sh")
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
maps = Path(temporary) / "maps"
|
||||
live = "1000-2000 r-xp 00000000 00:01 42 /app/libcoreclr.so"
|
||||
for line, expected in ((live, 0), (live + " (deleted)", 1), (live.replace(" 42 ", " 43 "), 1),
|
||||
(live + "\n" + live.replace("/app/", "/different/"), 1)):
|
||||
with self.subTest(line=line):
|
||||
maps.write_text(line + "\n", encoding="ascii")
|
||||
result = subprocess.run(["bash", "-c", 'source "$1"\nverify_mapped_coreclr "$2" "$3"',
|
||||
"map-control", str(script), str(maps), "42 /app/libcoreclr.so"],
|
||||
capture_output=True, text=True, timeout=5)
|
||||
self.assertEqual(result.returncode, expected, result.stderr)
|
||||
|
||||
def test_remote_override_fails_before_asking_docker(self):
|
||||
with patch.dict(os.environ, {"DOCKER_HOST": "tcp://example.invalid:2375"}), patch("bundle.subprocess.check_output") as docker:
|
||||
with self.assertRaisesRegex(ValueError, "override"):
|
||||
bundle.context_identity("local-control")
|
||||
docker.assert_not_called()
|
||||
|
||||
def test_bundle_file_set_runtime_and_package_graph(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary).resolve()
|
||||
app = root / "app"
|
||||
app.mkdir()
|
||||
elf = b"\x7fELF\x02\x01" + b"\x00" * 12 + b"\xb7\x00"
|
||||
(app / analyze.APP).write_bytes(elf)
|
||||
(app / analyze.APP).chmod(0o700)
|
||||
(app / "libcoreclr.so").write_bytes(elf)
|
||||
runtime = app / f"{analyze.APP}.runtimeconfig.json"
|
||||
write_json(runtime, {"runtimeOptions": {"tfm": "net10.0", "includedFrameworks": [
|
||||
{"name": "Microsoft.NETCore.App", "version": analyze.RUNTIME}]}})
|
||||
dependencies = app / f"{analyze.APP}.deps.json"
|
||||
write_json(dependencies, {"runtimeTarget": {"name": ".NETCoreApp,Version=v10.0/linux-arm64"},
|
||||
"libraries": {key: {} for key in bundle.SDK_PACKAGES | bundle.GATEWAY_PACKAGES}})
|
||||
modules = []
|
||||
for index, assembly in enumerate((analyze.APP, "Opc.Ua.Server", "System.Private.CoreLib",
|
||||
"ZB.MOM.WW.HistorianGateway.Client", "ZB.MOM.WW.HistorianGateway.Contracts"), 1):
|
||||
filename = f"{assembly}.dll"
|
||||
(app / filename).write_text("Synthetic metadata fixture\n", encoding="utf-8")
|
||||
modules.append({"file": f"app/{filename}", "assembly": assembly, "version": "1.0.0.0", "mvid": str(UUID(int=index))})
|
||||
tools = root / "tools"
|
||||
tools.mkdir()
|
||||
for name in bundle.TOOLS:
|
||||
(tools / name).write_text("Synthetic tool fixture\n", encoding="utf-8")
|
||||
receipt = {**analyze.SETTINGS, "kind": "bundle", "sourceRevision": REVISION, "image": IMAGE,
|
||||
"imageIdentity": {"id": IMAGE, "os": "linux", "architecture": "arm64"}, "dockerContext": CONTEXT,
|
||||
"sdkLibraries": sorted(bundle.SDK_PACKAGES), "gatewayLibraries": sorted(bundle.GATEWAY_PACKAGES),
|
||||
"managedModules": modules, "sourceFiles": {**dict.fromkeys(bundle.CANONICAL_SOURCES, "e" * 64), **{
|
||||
f"scripts/validation/opcua-lifecycle-memory/late-slope/{name}": analyze.digest(tools / name)
|
||||
for name in bundle.TOOLS}}, "files": bundle.manifest(root)}
|
||||
path = root / "receipt.json"
|
||||
write_json(path, receipt)
|
||||
approved = analyze.digest(path)
|
||||
bundle.verify_bundle(root, approved)
|
||||
extra = app / "extra"
|
||||
extra.touch()
|
||||
with self.assertRaisesRegex(ValueError, "file set"):
|
||||
bundle.verify_bundle(root, approved)
|
||||
extra.unlink()
|
||||
extra.symlink_to(app / "libcoreclr.so")
|
||||
with self.assertRaisesRegex(ValueError, "artifact type"):
|
||||
bundle.verify_bundle(root, approved)
|
||||
extra.unlink()
|
||||
write_json(runtime, {"runtimeOptions": {"tfm": "net10.0", "includedFrameworks": [
|
||||
{"name": "Microsoft.NETCore.App", "version": "10.0.3"}]}})
|
||||
receipt["files"] = bundle.manifest(root)
|
||||
write_json(path, receipt)
|
||||
with self.assertRaisesRegex(ValueError, "self-contained application runtime"):
|
||||
bundle.verify_bundle(root, analyze.digest(path))
|
||||
write_json(runtime, {"runtimeOptions": {"tfm": "net10.0", "includedFrameworks": [
|
||||
{"name": "Microsoft.NETCore.App", "version": analyze.RUNTIME}]}})
|
||||
write_json(dependencies, {"runtimeTarget": {"name": ".NETCoreApp,Version=v10.0/linux-arm64"}, "libraries": {}})
|
||||
receipt["files"] = bundle.manifest(root)
|
||||
write_json(path, receipt)
|
||||
with self.assertRaisesRegex(ValueError, "dependency|graph"):
|
||||
bundle.verify_bundle(root, analyze.digest(path))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
@@ -1 +0,0 @@
|
||||
__pycache__/
|
||||
@@ -1,95 +0,0 @@
|
||||
# Native empty-keychain control — negative retention result
|
||||
|
||||
The plain C control completed **200 private keychain create/delete/CFRelease
|
||||
operations successfully**, with `Security::AppleDatabase` heap inventory staying
|
||||
at **1 object / 768 shallow bytes** before, after the first operation, after 200,
|
||||
and after a five-second idle. This **does not reproduce** the retention seen in
|
||||
private-PFX and SDK configured-store loading. Empty native create/delete/release
|
||||
alone is therefore insufficient to explain that result on this machine.
|
||||
|
||||
This does not rule out deletion/resource interactions for populated imported
|
||||
keychains, identify the retaining owner, or assign an SDK, CLR or Apple defect.
|
||||
Private-key/certificate materialization and its associated native interactions
|
||||
remain distinct. No production mitigation, resource-budget decision, G4 pass or
|
||||
#799 closure follows from this control.
|
||||
|
||||
## Reviewed execution and isolation
|
||||
|
||||
Astra reviewed the actual C/Python source before execution and afterward
|
||||
independently verified all 207 JSONL rows, 200 ordered operations/status triples,
|
||||
reference balance, default/search-list fingerprints, all four native heap
|
||||
counts/bytes, FD/file counts, source/runner/binary hashes, cleanup and warnings.
|
||||
Only **one actual native execution** ran, serialized after the coordinator's other
|
||||
ownership control. Source is `PureAppleControl.c`; collector is `pure_apple.py`.
|
||||
|
||||
The child is a plain native C program linked only to Security.framework,
|
||||
CoreFoundation.framework and libSystem. It does not load certificates/PFX, the
|
||||
OPC UA SDK or CLR. `SecKeychainCreate` used a fresh random filename beneath its
|
||||
private mode-0700 task root, a generated password and `promptUser=false`. A returned
|
||||
keychain's path had to exactly match that generated private filename/backing file
|
||||
before deletion was allowed. Each returned create reference received exactly
|
||||
one `CFRelease`, including failure paths. The program made no default/search-list
|
||||
setter or restore call. Read-only `SecKeychainCopyDefault`,
|
||||
`SecKeychainCopySearchList` and `SecKeychainGetPath` produced hashed before/after
|
||||
fingerprints; owned Copy results were released, borrowed array elements were not
|
||||
released separately. Existing keychain paths/passwords were never logged.
|
||||
|
||||
Native checkpoints were before, first, 200 and five-second idle. Each parent
|
||||
snapshot used `heap --noContent -s` and numeric lsof FDs, with Mach task resident
|
||||
bytes reported by the child. It did not invoke GC or allocator-pressure APIs.
|
||||
The original fixed 180-second checkpoint/child limit, 20-second heap and
|
||||
five-second lsof limits, bounded final wait and terminate/kill reap remain in the
|
||||
collector; those probe/reap bounds can extend total wall time beyond 180 seconds.
|
||||
Actual child monotonic duration was **8.995 seconds**; parent wall time including
|
||||
probes was **9.288 seconds**. The child exited zero and was reaped.
|
||||
|
||||
## Actual results
|
||||
|
||||
| Checkpoint | AppleDatabase count / shallow bytes | Numeric FDs | Owned keychain files / FDs | RSS bytes |
|
||||
|---|---:|---:|---:|---:|
|
||||
| Before | 1 / 768 | 3 | 0 / 0 | 7,372,800 |
|
||||
| First | 1 / 768 | 3 | 0 / 0 | 8,028,160 |
|
||||
| 200 | 1 / 768 | 3 | 0 / 0 | 8,699,904 |
|
||||
| Five-second idle | 1 / 768 | 3 | 0 / 0 | 8,699,904 |
|
||||
|
||||
All **200 create/path/delete OSStatus triples were `(0, 0, 0)`**. Each create
|
||||
returned an owned reference, its private path was verified, and all **200/200**
|
||||
references were released exactly once. All read-only default/path/search-list
|
||||
query statuses were zero. Before/after fingerprints were identical, with search
|
||||
list count **2** at both observations. Four query-owned Copy references were
|
||||
released across the two fingerprint collections. No list setter was invoked.
|
||||
|
||||
Default fingerprint:
|
||||
`08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63`.
|
||||
Search-list fingerprint:
|
||||
`c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c`.
|
||||
|
||||
Owned keychain files were already zero before harness cleanup. The fresh owned
|
||||
fixture root was then removed. Native class count is a heap classification, not
|
||||
an open-handle count or an exclusive attribution of the modest RSS change.
|
||||
|
||||
The first attempt stopped at **compilation**, before a native child or API call:
|
||||
strict C11 headers did not declare `explicit_bzero`. Replacing only that
|
||||
caller-owned buffer wipe with a volatile-byte wipe made the build succeed; empty
|
||||
fixture creation was moved after successful compilation. The failed build is
|
||||
retained separately. Both compile attempts emitted **five unsuppressed
|
||||
deprecated-public-API warnings** for the intentionally exercised legacy keychain
|
||||
APIs. This is not a zero-warning build and no warning suppression was added.
|
||||
|
||||
## Evidence and reproduction
|
||||
|
||||
Selected, home-path-redacted receipts are under
|
||||
`evidence/2026-11-10-pure-apple/`; `verification.json` retains the unchanged local
|
||||
raw receipt hashes. Actual raw output is
|
||||
`/tmp/opcua2-pure-apple-20261110b`; the first compile-only failure is
|
||||
`/tmp/opcua2-pure-apple-20261110a`. Raw native snapshots stay private/local.
|
||||
|
||||
```sh
|
||||
python3 scripts/validation/opcua-lifecycle-memory/native-retention/pure_apple.py \
|
||||
--output /tmp/opcua2-pure-apple-FRESH
|
||||
```
|
||||
|
||||
The output must be fresh. Fixed counts are not configurable; all generated paths
|
||||
are task-owned and no user/fleet PKI is used. This negative control refines the
|
||||
[A/B directory-load findings](README.md), and does not approve another experiment,
|
||||
a native workaround, a public upstream post or a long run.
|
||||
@@ -1,123 +0,0 @@
|
||||
// Diagnostic only: private SecKeychainCreate/Delete/CFRelease, with no certificate, PFX, SDK or CLR.
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#include <mach/mach.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define REPETITIONS 200
|
||||
static char root[PATH_MAX];
|
||||
static struct timespec started;
|
||||
static unsigned created_refs, released_refs, query_releases;
|
||||
static double elapsed(void) {
|
||||
struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return (double)(now.tv_sec-started.tv_sec)+(double)(now.tv_nsec-started.tv_nsec)/1e9;
|
||||
}
|
||||
static void die(const char *message) {
|
||||
fprintf(stdout,"{\"kind\":\"failed\",\"message\":\"%s\",\"createdRefs\":%u,\"releasedRefs\":%u,\"elapsedSeconds\":%.6f}\n",message,created_refs,released_refs,elapsed());
|
||||
fflush(stdout); exit(1);
|
||||
}
|
||||
static void hex(const unsigned char *bytes, size_t length, char *out) {
|
||||
const char *alphabet="0123456789abcdef";
|
||||
for(size_t i=0;i<length;i++){out[i*2]=alphabet[bytes[i]>>4];out[i*2+1]=alphabet[bytes[i]&15];}
|
||||
out[length*2]=0;
|
||||
}
|
||||
static void wipe(void *memory, size_t length) {
|
||||
volatile unsigned char *bytes=(volatile unsigned char *)memory;
|
||||
while(length--)*bytes++=0;
|
||||
}
|
||||
static OSStatus keychain_path(SecKeychainRef keychain, char *path) {
|
||||
UInt32 length=PATH_MAX-1;
|
||||
OSStatus status=SecKeychainGetPath(keychain,&length,path);
|
||||
if(status==errSecSuccess && length<PATH_MAX)path[length]=0;
|
||||
return status;
|
||||
}
|
||||
struct fingerprint { char default_sha[65], search_sha[65]; CFIndex search_count; };
|
||||
static struct fingerprint fingerprint(const char *stage) {
|
||||
SecKeychainRef default_keychain=NULL;
|
||||
CFArrayRef search=NULL;
|
||||
struct fingerprint out; memset(&out,0,sizeof(out));
|
||||
char path[PATH_MAX]; memset(path,0,sizeof(path));
|
||||
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
||||
OSStatus default_status=SecKeychainCopyDefault(&default_keychain);
|
||||
OSStatus default_path_status=default_keychain?keychain_path(default_keychain,path):errSecInvalidKeychain;
|
||||
if(default_status==errSecSuccess && default_path_status==errSecSuccess){CC_SHA256(path,(CC_LONG)strlen(path),digest);hex(digest,sizeof(digest),out.default_sha);}
|
||||
if(default_keychain){CFRelease(default_keychain);query_releases++;default_keychain=NULL;}
|
||||
OSStatus search_status=SecKeychainCopySearchList(&search);
|
||||
OSStatus search_path_status=errSecSuccess;
|
||||
CC_SHA256_CTX hash; CC_SHA256_Init(&hash);
|
||||
if(search_status==errSecSuccess && search){
|
||||
out.search_count=CFArrayGetCount(search);
|
||||
uint64_t count=(uint64_t)out.search_count; CC_SHA256_Update(&hash,&count,sizeof(count));
|
||||
for(CFIndex i=0;i<out.search_count;i++){
|
||||
// CFArray values are borrowed. Releasing the owned array balances its element references.
|
||||
SecKeychainRef borrowed=(SecKeychainRef)CFArrayGetValueAtIndex(search,i);
|
||||
memset(path,0,sizeof(path)); OSStatus status=keychain_path(borrowed,path);
|
||||
if(status!=errSecSuccess){search_path_status=status;break;}
|
||||
uint32_t length=(uint32_t)strlen(path);CC_SHA256_Update(&hash,&length,sizeof(length));CC_SHA256_Update(&hash,path,length);
|
||||
}
|
||||
}
|
||||
CC_SHA256_Final(digest,&hash);hex(digest,sizeof(digest),out.search_sha);
|
||||
if(search){CFRelease(search);query_releases++;search=NULL;}
|
||||
fprintf(stdout,"{\"kind\":\"fingerprint\",\"stage\":\"%s\",\"defaultStatus\":%d,\"defaultPathStatus\":%d,\"searchStatus\":%d,\"searchPathStatus\":%d,\"defaultSha256\":\"%s\",\"searchSha256\":\"%s\",\"searchCount\":%ld,\"ownedQueryReferencesReleased\":%u}\n",stage,(int)default_status,(int)default_path_status,(int)search_status,(int)search_path_status,out.default_sha,out.search_sha,(long)out.search_count,query_releases);fflush(stdout);
|
||||
if(default_status || default_path_status || search_status || search_path_status)die("Read-only keychain fingerprint failed");
|
||||
return out;
|
||||
}
|
||||
static void checkpoint(const char *stage, unsigned operations) {
|
||||
struct mach_task_basic_info info; mach_msg_type_number_t count=MACH_TASK_BASIC_INFO_COUNT;
|
||||
kern_return_t status=task_info(mach_task_self(),MACH_TASK_BASIC_INFO,(task_info_t)&info,&count);
|
||||
if(status!=KERN_SUCCESS)die("task_info failed");
|
||||
struct timespec wall;clock_gettime(CLOCK_REALTIME,&wall);struct tm utc;gmtime_r(&wall.tv_sec,&utc);
|
||||
char stamp[40];strftime(stamp,sizeof(stamp),"%Y-%m-%dT%H:%M:%S",&utc);
|
||||
fprintf(stdout,"{\"kind\":\"checkpoint\",\"mode\":\"pure-apple\",\"stage\":\"%s\",\"operations\":%u,\"processId\":%d,\"utc\":\"%s.%03ldZ\",\"elapsedSeconds\":%.6f,\"rssBytes\":%llu,\"createdRefs\":%u,\"releasedRefs\":%u,\"managedRuntimePresent\":false}\n",stage,operations,getpid(),stamp,wall.tv_nsec/1000000,elapsed(),(unsigned long long)info.resident_size,created_refs,released_refs);fflush(stdout);
|
||||
char next[PATH_MAX];int n=snprintf(next,sizeof(next),"%s/continue-%s",root,stage);if(n<0 || (size_t)n>=sizeof(next))die("Checkpoint path overflow");
|
||||
while(access(next,F_OK)!=0){if(elapsed()>180)die("Checkpoint deadline exceeded");struct timespec pause={0,25000000};nanosleep(&pause,NULL);}
|
||||
}
|
||||
static int absent(const char *path){struct stat state;if(lstat(path,&state)==0)return 0;return errno==ENOENT;}
|
||||
static void operation(unsigned iteration) {
|
||||
unsigned char random[48];if(SecRandomCopyBytes(kSecRandomDefault,sizeof(random),random)!=errSecSuccess)die("Secure random failed");
|
||||
char suffix[33],password[65];hex(random,16,suffix);hex(random+16,32,password);wipe(random,sizeof(random));
|
||||
char path[PATH_MAX],backing[PATH_MAX];int n=snprintf(path,sizeof(path),"%s/tmp/native-retention-%s.keychain",root,suffix);
|
||||
if(n<0 || (size_t)n>=sizeof(path))die("Fixture path overflow");
|
||||
n=snprintf(backing,sizeof(backing),"%s-db",path);if(n<0 || (size_t)n>=sizeof(backing))die("Fixture backing path overflow");
|
||||
if(!absent(path)||!absent(backing))die("Generated private fixture path already exists");
|
||||
SecKeychainRef keychain=NULL;
|
||||
OSStatus create_status=SecKeychainCreate(path,(UInt32)strlen(password),password,false,NULL,&keychain);
|
||||
wipe(password,sizeof(password));
|
||||
OSStatus path_status=errSecInvalidKeychain,delete_status=INT32_MIN;
|
||||
int verified=0,released=0;
|
||||
if(keychain){
|
||||
created_refs++;
|
||||
char actual[PATH_MAX];memset(actual,0,sizeof(actual));path_status=keychain_path(keychain,actual);
|
||||
// Only a returned reference whose path is exactly this generated private fixture can be deleted.
|
||||
verified=path_status==errSecSuccess && (!strcmp(actual,path)||!strcmp(actual,backing));
|
||||
if(verified)delete_status=SecKeychainDelete(keychain);
|
||||
// Exactly one CFRelease for this returned owned reference, irrespective of delete status.
|
||||
CFRelease(keychain);keychain=NULL;released_refs++;released=1;
|
||||
}
|
||||
fprintf(stdout,"{\"kind\":\"operation\",\"iteration\":%u,\"createStatus\":%d,\"pathStatus\":%d,\"deleteStatus\":%d,\"returnedRef\":%s,\"privatePathVerified\":%s,\"releasedExactlyOnce\":%s}\n",iteration,(int)create_status,(int)path_status,(int)delete_status,released?"true":"false",verified?"true":"false",released?"true":"false");fflush(stdout);
|
||||
if(create_status || path_status || delete_status || !verified || !released)die("Private keychain lifecycle operation failed");
|
||||
}
|
||||
int main(int argc,char **argv) {
|
||||
clock_gettime(CLOCK_MONOTONIC,&started);
|
||||
if(argc!=2 || !realpath(argv[1],root))die("Expected existing private fixture root");
|
||||
struct stat state;if(stat(root,&state) || !S_ISDIR(state.st_mode) || (state.st_mode&077))die("Fixture root must be mode0700");
|
||||
struct fingerprint before=fingerprint("before");checkpoint("before",0);
|
||||
for(unsigned i=1;i<=REPETITIONS;i++){operation(i);if(i==1)checkpoint("first",i);}
|
||||
checkpoint("repeated",REPETITIONS);
|
||||
struct timespec idle={5,0};while(nanosleep(&idle,&idle)!=0){if(errno!=EINTR)die("Idle delay failed");}
|
||||
struct fingerprint after=fingerprint("after");
|
||||
checkpoint("idle",REPETITIONS);
|
||||
int unchanged=!strcmp(before.default_sha,after.default_sha)&&!strcmp(before.search_sha,after.search_sha)&&before.search_count==after.search_count;
|
||||
if(!unchanged || created_refs!=REPETITIONS || released_refs!=REPETITIONS)die("Fingerprint or native ownership guard failed");
|
||||
fprintf(stdout,"{\"kind\":\"complete\",\"operations\":200,\"createdRefs\":%u,\"releasedRefs\":%u,\"readOnlyDefaultAndSearchListUnchanged\":true,\"elapsedSeconds\":%.6f,\"fullSoakGate\":false}\n",created_refs,released_refs,elapsed());fflush(stdout);return 0;
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
# macOS private-key reload native retention — #799
|
||||
|
||||
The bounded control identifies **configured-directory private-key loading** as a
|
||||
trigger for continuing `Security::AppleDatabase` heap inventory on this machine,
|
||||
while observed SDK certificate-core ownership and tracked .NET temporary-keychain
|
||||
ownership return to zero. No narrow built-in application ownership correction was
|
||||
found that preserves the current raw-session factory, Directory PKI, certificate
|
||||
selection/update behavior and certificate properties. **#799 remains open.** This
|
||||
is private reproduction/support material, not an approved production mitigation.
|
||||
|
||||
Only this new subfolder was changed. No product source, trust policy, SDK version,
|
||||
certificate factory/crypto provider, exportability, key storage format, existing
|
||||
PKI or resource budget was changed. No public upstream issue/message was posted.
|
||||
|
||||
## Reviewed, executed control
|
||||
|
||||
Astra reviewed the actual source and installed-runtime decompile before execution,
|
||||
approved one fixed **200-acquisition** run per arm as attribution-only evidence,
|
||||
and afterward independently matched all ten raw heap counts/bytes, checkpoint and
|
||||
completion counts, source hashes, installed crypto hash and eight SDK DLL hashes.
|
||||
The configured-store versus registry distinction below is supported by inspected
|
||||
upstream regression source; that upstream regression test was **not executed**.
|
||||
|
||||
Both arms ran in separate fresh processes on macOS **26.5 arm64**, .NET SDK
|
||||
**10.0.403**, runtime **10.0.14**. A normal SDK ApplicationInstance created one RSA
|
||||
application PKI; its persisted tree was copied into separate private arm roots.
|
||||
Both used the same application URI, public DER identity and private key. Normal
|
||||
SDK configuration validation/certificate checks and teardown were identical. The
|
||||
loop called these public APIs, disposing each returned owner before checkpoints:
|
||||
|
||||
| Arm | Public acquisition, repeated exactly 200 times |
|
||||
|---|---|
|
||||
| Store | `SecurityConfiguration.FindApplicationCertificateAsync(Basic256Sha256, privateKey: true, ...)` |
|
||||
| Registry | `ICertificateRegistry.AcquireApplicationCertificateBySecurityPolicy(Basic256Sha256)` |
|
||||
|
||||
Each arm sampled ready, first acquisition, acquisition 200, application disposed,
|
||||
and after a fixed five-second idle. Every checkpoint used the same full-GC /
|
||||
finalizer / full-GC / 250 ms schedule, then a parent-controlled heap/lsof barrier.
|
||||
Matched initial/first/last RSA sign-and-verify checks confirmed private-key use.
|
||||
No iteration called `AsX509Certificate2`; no network, server or session was opened.
|
||||
`AutoAcceptUntrustedCertificates=false` stayed configured; this key-acquisition
|
||||
control makes no additional peer-validation wire claim.
|
||||
|
||||
Allocation-stack tracking was enabled in **both** arms, so its allocation/GC cost
|
||||
is part of these observations. The 180-second child cancellation/checkpoint
|
||||
limit is not a strict total wall deadline: a running heap probe (20 seconds),
|
||||
lsof probe (five seconds), final wait and bounded terminate/kill reap can add
|
||||
bounded overhead. Stdout is a file, with no unbounded `communicate` or pipe drain.
|
||||
The recorded artifact-creation-to-result-write wall interval was **34.699 seconds**
|
||||
(filesystem timestamps, not a monotonic acceptance gate). Ready-to-idle checkpoint
|
||||
intervals were **21.504 seconds store** and **9.123 seconds registry**, including
|
||||
probe barriers. Both process exits were zero and all children were reaped.
|
||||
|
||||
## Native inventory and ownership results
|
||||
|
||||
| Checkpoint | Store AppleDatabase | Registry AppleDatabase | Tracked runtime keychains, each arm | Outstanding SDK cores, each arm | Temporary keychain files, each arm |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| Ready | 3 | 3 | 1 | 1 | 1 |
|
||||
| First acquisition | 4 | 3 | 1 | 1 | 1 |
|
||||
| Acquisition 200 | 203 | 3 | 1 | 1 | 1 |
|
||||
| Application disposed | 203 | 3 | 0 | 0 | 0 |
|
||||
| Five-second idle | 203 | 3 | 0 | 0 | 0 |
|
||||
|
||||
Configured PKI FDs and temporary-keychain FDs were **zero at every checkpoint**.
|
||||
One other task-TMPDIR descriptor remained in each process; it is reported
|
||||
separately and is not labelled a keychain descriptor. Total numeric FDs were
|
||||
110 ready / 112 final in both arms. Manager disposal was observed through an
|
||||
exact-SDK, read-only `m_disposed` boolean probe. Store certificate-core counters
|
||||
finished **407 created / 407 disposed**; registry finished **7 / 7**. These public
|
||||
counters concern underlying certificate cores, not every AddRef wrapper.
|
||||
|
||||
The exact installed runtime's internal temporary-keychain dictionary was read
|
||||
under the same dictionary monitor, with a one-second bounded acquisition and
|
||||
exact informational-version/type/field guards. Only its count was read; no native
|
||||
pointer, handle, key or certificate material was enumerated or modified. Its
|
||||
count returning zero establishes no remaining entries in that managed lookup.
|
||||
The installed cleanup code removes the entry **before** calling native
|
||||
`SecKeychainDelete`, suppresses delete errors, and then releases the CF handle.
|
||||
The actual installed base `SafeKeychainHandle.ReleaseHandle` was separately
|
||||
decompiled and does call `Interop.CoreFoundation.CFRelease(handle)`, then zeros
|
||||
its handle. Apple's [SecKeychainDelete documentation](https://developer.apple.com/documentation/security/seckeychaindelete(_:).md)
|
||||
distinguishes file/keychain deletion from releasing keychain-object memory; this
|
||||
inspection finds the separate CFRelease in the installed runtime, not an obvious
|
||||
missing base-release implementation. These are inspected calls, not native
|
||||
return-status instrumentation. Therefore lookup zero does **not** prove that
|
||||
native deletion succeeded.
|
||||
|
||||
| Memory observation | Store ready → final idle | Registry ready → final idle |
|
||||
|---|---:|---:|
|
||||
| Managed live bytes | 831,080 → 1,222,192 | 831,128 → 1,130,616 |
|
||||
| RSS bytes | 87,621,632 → 115,130,368 | 87,654,400 → 97,927,168 |
|
||||
| Compiled methods | 1,192 → 4,638 | 1,192 → 2,251 |
|
||||
|
||||
RSS includes different JIT, tracking, GC and allocator effects; this comparison
|
||||
is not an exclusive native-byte attribution or a performance budget. The native
|
||||
class's shallow heap bytes were 2,304 → 155,904 in store and 2,304 → 2,304 in
|
||||
registry (768 bytes per classified object). Shallow class bytes exclude owned
|
||||
allocations and do not explain the entire RSS difference. `PrivateMemorySize64`
|
||||
returned zero on this runtime and is not used as a private-memory result.
|
||||
|
||||
`heap --noContent -s` reports allocations classified as the C++
|
||||
`Security::AppleDatabase` class. Apple's published file-database source declares
|
||||
that class as a `Database` subclass with database open/close/delete methods and
|
||||
owned file/modifier state; it is not a file-descriptor counter. The published
|
||||
source is conceptual evidence, **not** a claim that it is the exact source build
|
||||
of this installed Security.framework. Retaining classified heap objects after
|
||||
observed closure is different from proving an open handle, failed native delete,
|
||||
or the identity of the retaining native owner. See the pinned
|
||||
[Apple class definition](https://github.com/apple-oss-distributions/Security/blob/db15acbe6a7f257a859ad9a3bb86097bfe0679d9/OSX/libsecurity_filedb/lib/AppleDatabase.h#L485).
|
||||
|
||||
The leaf DER SHA-256 was identical before/after and across arms:
|
||||
`fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2`.
|
||||
After samples and process exits, every seed/arm PKI, TMPDIR and data fixture
|
||||
was removed; cleanup receipt is true. Raw native snapshots stay local and private.
|
||||
|
||||
## Exact SDK path and public API limits
|
||||
|
||||
The inspected SDK checkout is the clean **2.0.1** tag at commit
|
||||
`07e62f72500cc0923a2bab940653c8c1116fa286`; the control references immutable actual
|
||||
published SDK 2.0.1 DLLs, with all eight hashes in `evidence/2026-11-10/provenance.json`.
|
||||
|
||||
| Source, pinned to the exact SDK commit | Relevant behavior |
|
||||
|---|---|
|
||||
| [DefaultSessionFactory.CreateChannelAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Client/Session/DefaultSessionFactory.cs#L406) | Loads a private certificate through the internal overload that defaults registry use to false. |
|
||||
| [DefaultSessionFactory private CreateAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Client/Session/DefaultSessionFactory.cs#L579) | Constructs the raw Session with null certificate/chain. |
|
||||
| [Session.LoadInstanceCertificateAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Client/Session/Session.cs#L6335) | Opening that Session independently loads its private certificate; registry preference depends on a channel manager, absent in the current raw factory. |
|
||||
| [Session.LoadInstanceCertificateEntryAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Client/Session/Session.cs#L6432) | Documents configured-store selection for unmanaged callers and registry preference for managed callers. |
|
||||
| [SecurityConfiguration.FindApplicationCertificateAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Core/Security/Certificates/SecurityConfiguration.cs#L182) | Private-key branch calls registry-less CertificateIdentifierResolver.LoadPrivateKeyAsync. |
|
||||
| [CertificateIdentifierResolver.LoadPrivateKeyCoreAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Core/Security/Certificates/CertificateIdentifierResolver.cs#L249) | Opens the configured store and asks it to load the private key; returned reference is caller-owned. |
|
||||
| [DirectoryCertificateStore.LoadPrivateKeyAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs#L758) | For PFX, macOS storage flags omit EphemeralKeySet and include Exportable, then import through X509CertificateLoader.LoadPkcs12. No public per-store private-key cache/flag setting is offered. |
|
||||
| [ApplicationConfiguration.ValidateAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs#L735), [ApplicationInstance.CheckOrCreateCertificateAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Configuration/ApplicationInstance.cs#L425), [ServerBase.OnServerStartingAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Core/Stack/Server/ServerBase.cs#L1887) | Application validation, normal own-certificate checking and server bring-up also load configured private certificates. Checking disposes its temporary certificate; registry replacement disposes old entries. |
|
||||
| [Certificate.AsX509Certificate2](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/src/Opc.Ua.Security.Certificates/X509Certificate/Certificate.cs#L258) | Nonvirtual export/reimport copy for exportable private keys. Existing isolated controls demonstrate its PFX retention trigger, but prior sampled real-workload stacks identified directory loading as the dominant sampled import path. |
|
||||
|
||||
`CertificateIdentifier` has **no Certificate preload/cache property** and only a
|
||||
public default constructor. Actual-binary public API inventory is retained in
|
||||
`seed-api-inventory.jsonl`. `RawData` carries public encoded certificate material;
|
||||
its setter parses `Certificate.FromRawData` and derives metadata. It cannot carry
|
||||
the reusable private Certificate owner needed by the raw private-key load path.
|
||||
The [exact-tag manager documentation](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/docs/CertificateManager.md#materializing-a-certificate-from-a-certificateidentifier)
|
||||
explicitly places materialized ownership in the manager registry.
|
||||
|
||||
The public registry acquisition API is reference-counted and supported. However,
|
||||
substituting it in the raw session path changes certificate selection semantics:
|
||||
[UnmanagedCertificateLoadHonorsAnExplicitConfiguredStoreReplacementAsync](https://github.com/OPCFoundation/UA-.NETStandard/blob/07e62f72500cc0923a2bab940653c8c1116fa286/tests/Opc.Ua.Client.Tests/Session/SessionCertificateRotationRegressionTests.cs#L198)
|
||||
requires a configured replacement to win over an older registry certificate and
|
||||
verifies the registry API is never called. This is **inspected upstream test
|
||||
source, not a test run here**. A cache/factory rewrite must additionally preserve
|
||||
update/removal visibility, cancellation/fault cleanup, concurrent owners,
|
||||
reconnect and certificate/issuer-chain selection; the B arm proves none of those
|
||||
replacement semantics. ChannelManagerSessionFactory changes architecture and was
|
||||
not used. Overriding/reimplementing channel and session construction is not a
|
||||
narrow application disposal fix.
|
||||
|
||||
Production source at `ed60970fc294ab171a80cda1b57942a7130b4c39` was inspected:
|
||||
[OpcUaApplicationHost](../../../../src/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer/OpcUaApplicationHost.cs)
|
||||
assigns configuration ownership before async validation and disposes its
|
||||
ApplicationInstance; Shared transfers manager lifetime to the session adapter
|
||||
and disposes failed configurations; driver/browser release their owned
|
||||
ApplicationInstance after session cleanup. No missing owner was identified in
|
||||
those paths. The store arm already keeps its one application/configuration and
|
||||
registry alive across all 200 acquisitions, so simply lengthening that
|
||||
application owner cannot remove these private-key imports. Existing full-client
|
||||
lifecycle disposal checks are complementary
|
||||
coordinator evidence, not additional executions in this control.
|
||||
|
||||
## Runtime dependency and upstream-ready boundary
|
||||
|
||||
Actual installed `System.Security.Cryptography.dll` informational version:
|
||||
`10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa`.
|
||||
SHA-256: `f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a`.
|
||||
|
||||
The official .NET `v10.0.14` tag resolves to
|
||||
`6aa72daa24f66c01c3d7b6a32519e9d21396deec`, different from the installed binary's
|
||||
informational commit. It is not presented as exact installed source. Read-only
|
||||
ILSpy inspection of the **actual binary** verified the temporary-keychain
|
||||
creation, dictionary/monitor and release behavior used by diagnostics. Paths and
|
||||
hashes of those retained local decompilations are in `verification.json`.
|
||||
|
||||
The public runtime source provides matching context for
|
||||
[temporary keychain creation during non-persisted import and unsupported EphemeralKeySet](https://github.com/dotnet/runtime/blob/6aa72daa24f66c01c3d7b6a32519e9d21396deec/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.macOS.cs)
|
||||
and [tracked-keychain release ordering](https://github.com/dotnet/runtime/blob/6aa72daa24f66c01c3d7b6a32519e9d21396deec/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Keychain.macOS.cs).
|
||||
Microsoft documents that macOS PFX private-key loading requires a keychain and
|
||||
cannot use EphemeralKeySet in its [cross-platform cryptography guide](https://learn.microsoft.com/en-us/dotnet/standard/security/cross-platform-cryptography#read-a-pkcs12pfx-file).
|
||||
Changing those flags, exportability, storage format or native crypto was not an
|
||||
application mitigation attempted here.
|
||||
|
||||
The remaining dependency is an upstream/platform investigation of why the
|
||||
classified native file-database objects remain after observed SDK owner release,
|
||||
tracked runtime owner release and backing-file cleanup, and whether there is a
|
||||
supported correction at that boundary. Native delete status and the retaining
|
||||
C++ owner are still unknown. This control does not identify a specific .NET or
|
||||
Apple defect/fix. An upstream SDK improvement would also need to avoid redundant
|
||||
imports **without losing the existing raw configured-store semantics**. No
|
||||
supported application-only correction meeting the stated constraints was proven.
|
||||
|
||||
## Private reproduction and evidence
|
||||
|
||||
```sh
|
||||
python3 scripts/validation/opcua-lifecycle-memory/native-retention/run.py \
|
||||
--references /tmp/opcua2-publish-hg100-20261110/linux-arm64/host \
|
||||
--output /tmp/opcua2-native-reload-FRESH
|
||||
```
|
||||
|
||||
This builds only the standalone control against existing actual SDK DLLs, never
|
||||
rebuilds product code, requires the exact installed runtime diagnostic layout,
|
||||
and refuses an existing output directory. The fixed repetition count is not
|
||||
configurable. Use a private fresh root and serialize with other ownership/native
|
||||
controls. The checked-in selected receipts are in `evidence/2026-11-10/`;
|
||||
raw artifacts are `/tmp/opcua2-native-reload-20261110a`. Raw heap/lsof output and
|
||||
any failed-run private fixture material must not be redistributed wholesale.
|
||||
|
||||
No long run, deployment, trust weakening, SDK fork/version change, budget change,
|
||||
public upstream post or #799 closure is authorized or claimed by these results.
|
||||
|
||||
A separately reviewed [plain native Apple empty-keychain control](PURE_APPLE.md)
|
||||
then executed 200 successful create/delete/CFRelease operations and kept native
|
||||
AppleDatabase at 1 throughout. That negative result rules out empty native
|
||||
create/delete/release alone as sufficient here; it does not identify the
|
||||
private-key/certificate import retaining owner.
|
||||
@@ -1,176 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Configuration;
|
||||
using Opc.Ua.Security.Certificates;
|
||||
|
||||
internal static class ReloadControl
|
||||
{
|
||||
const string Uri = "urn:localhost:NativeRetention.Control";
|
||||
const int Repetitions = 200;
|
||||
static readonly byte[] Challenge = Encoding.UTF8.GetBytes("native-retention-diagnostic-only");
|
||||
static string Root = "";
|
||||
static string Hash(Certificate cert) => Convert.ToHexString(SHA256.HashData(cert.RawData)).ToLowerInvariant();
|
||||
static void Require(bool yes, string message) { if (!yes) throw new InvalidOperationException(message); }
|
||||
static ApplicationConfiguration Configuration(string pki, ITelemetryContext telemetry) => new(telemetry)
|
||||
{
|
||||
ApplicationName = "NativeRetention.Control", ApplicationUri = Uri, ApplicationType = ApplicationType.Client,
|
||||
SecurityConfiguration = new SecurityConfiguration
|
||||
{
|
||||
ApplicationCertificate = new CertificateIdentifier { StoreType = CertificateStoreType.Directory,
|
||||
StorePath = Path.Combine(pki, "own"), SubjectName = "CN=NativeRetention.Control" },
|
||||
TrustedPeerCertificates = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(pki, "trusted") },
|
||||
TrustedIssuerCertificates = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(pki, "issuers") },
|
||||
RejectedCertificateStore = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = Path.Combine(pki, "rejected") },
|
||||
AutoAcceptUntrustedCertificates = false,
|
||||
},
|
||||
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 15000 },
|
||||
};
|
||||
static async Task<ApplicationInstance> Open(string pki, ITelemetryContext telemetry, CancellationToken ct)
|
||||
{
|
||||
var app = new ApplicationInstance(telemetry) { ApplicationType = ApplicationType.Client,
|
||||
ApplicationName = "NativeRetention.Control", ApplicationConfiguration = Configuration(pki, telemetry) };
|
||||
try
|
||||
{
|
||||
await app.ApplicationConfiguration!.ValidateAsync(ApplicationType.Client, ct);
|
||||
Require(await app.CheckApplicationInstanceCertificatesAsync(true, null, ct), "Normal application certificate check failed");
|
||||
return app;
|
||||
}
|
||||
catch { await app.DisposeAsync(); throw; }
|
||||
}
|
||||
static bool ManagerDisposed(ICertificateManager manager)
|
||||
{
|
||||
Require(manager.GetType().FullName == "Opc.Ua.CertificateManager" && manager.GetType().Assembly.GetName().Version?.ToString() == "2.0.1.0", "Exact SDK diagnostic layout changed");
|
||||
var field = manager.GetType().GetField("m_disposed", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
|
||||
Require(field?.FieldType == typeof(bool), "Exact SDK disposal bool missing");
|
||||
return (bool)field!.GetValue(manager)!;
|
||||
}
|
||||
static int RuntimeTemporaryKeychainCount()
|
||||
{
|
||||
var assembly = typeof(X509Certificate2).Assembly;
|
||||
Require(assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion == "10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa", "Exact runtime diagnostic build changed");
|
||||
var type = assembly.GetType("System.Security.Cryptography.Apple.SafeTemporaryKeychainHandle", throwOnError: true)!;
|
||||
var field = type.GetField("s_lookup", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
|
||||
Require(field is not null && field.FieldType.IsGenericType && field.FieldType.GetGenericTypeDefinition() == typeof(Dictionary<,>)
|
||||
&& field.FieldType.GetGenericArguments()[0] == typeof(IntPtr) && field.FieldType.GetGenericArguments()[1] == type,
|
||||
"Exact runtime keychain dictionary layout changed");
|
||||
var lookup = (IDictionary)(field!.GetValue(null) ?? throw new InvalidOperationException("Runtime keychain dictionary absent"));
|
||||
Require(Monitor.TryEnter(lookup, TimeSpan.FromSeconds(1)), "Runtime keychain monitor did not become available");
|
||||
try { return lookup.Count; }
|
||||
finally { Monitor.Exit(lookup); }
|
||||
}
|
||||
static void ValidateKey(Certificate certificate, string expected, bool sign)
|
||||
{
|
||||
Require(certificate.HasPrivateKey && Hash(certificate) == expected, "Wrong/missing private certificate");
|
||||
if (!sign) return;
|
||||
using var privateKey = certificate.GetRSAPrivateKey();
|
||||
using var publicKey = certificate.GetRSAPublicKey();
|
||||
Require(privateKey is not null && publicKey is not null, "Expected normal SDK RSA application certificate");
|
||||
var signature = privateKey!.SignData(Challenge, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
Require(publicKey!.VerifyData(Challenge, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1), "Private key mismatch");
|
||||
}
|
||||
static async Task Stage(string mode, string stage, int operations, bool disposed, CancellationToken ct)
|
||||
{
|
||||
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
|
||||
await Task.Delay(250, ct);
|
||||
using var process = Process.GetCurrentProcess(); process.Refresh();
|
||||
Console.WriteLine(JsonSerializer.Serialize(new { kind = "checkpoint", mode, stage, operations, processId = Environment.ProcessId,
|
||||
utc = DateTimeOffset.UtcNow, managerDisposed = disposed, managedBytes = GC.GetTotalMemory(false), rssBytes = process.WorkingSet64,
|
||||
privateBytes = process.PrivateMemorySize64, allocatedBytes = GC.GetTotalAllocatedBytes(), compiledMethods = JitInfo.GetCompiledMethodCount(),
|
||||
gc = new[] { GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2) },
|
||||
certificateCoresCreated = Certificate.InstancesCreated, certificateCoresDisposed = Certificate.InstancesDisposed,
|
||||
certificateCoresOutstanding = Certificate.InstancesLeaked,
|
||||
runtimeTrackedTemporaryKeychains = RuntimeTemporaryKeychainCount() }));
|
||||
Console.Out.Flush();
|
||||
while (!File.Exists(Path.Combine(Root, "continue-" + stage))) await Task.Delay(25, ct);
|
||||
}
|
||||
static async Task Arm(string mode, CancellationToken ct)
|
||||
{
|
||||
var telemetry = DefaultTelemetry.Create(_ => { });
|
||||
var pki = Path.Combine(Root, "pki");
|
||||
var before = Directory.GetFiles(pki, "*.der", SearchOption.AllDirectories).Where(p => p.Contains(Path.DirectorySeparatorChar + "own" + Path.DirectorySeparatorChar + "certs" + Path.DirectorySeparatorChar, StringComparison.Ordinal))
|
||||
.Select(p => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(p)))).Order().ToArray();
|
||||
Require(before.Length == 1, "Expected one copied own DER certificate");
|
||||
ApplicationInstance? app = null;
|
||||
try
|
||||
{
|
||||
app = await Open(pki, telemetry, ct);
|
||||
var config = app.ApplicationConfiguration!;
|
||||
var manager = config.CertificateManager;
|
||||
string expected;
|
||||
using (var entry = manager.AcquireApplicationCertificateBySecurityPolicy(SecurityPolicies.Basic256Sha256))
|
||||
{
|
||||
Require(entry is not null, "Normal initialization did not populate registry");
|
||||
expected = Hash(entry!.Certificate); ValidateKey(entry.Certificate, expected, true);
|
||||
}
|
||||
await Stage(mode, "ready", 0, ManagerDisposed(manager), ct);
|
||||
for (var i = 1; i <= Repetitions; i++)
|
||||
{
|
||||
if (mode == "store")
|
||||
{
|
||||
using var certificate = await config.SecurityConfiguration.FindApplicationCertificateAsync(
|
||||
SecurityPolicies.Basic256Sha256, true, telemetry, ct).WaitAsync(ct);
|
||||
Require(certificate is not null, "Configured-store acquisition failed");
|
||||
ValidateKey(certificate!, expected, i is 1 or Repetitions);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var entry = manager.AcquireApplicationCertificateBySecurityPolicy(SecurityPolicies.Basic256Sha256);
|
||||
Require(entry is not null, "Registry acquisition failed");
|
||||
ValidateKey(entry!.Certificate, expected, i is 1 or Repetitions);
|
||||
}
|
||||
if (i is 1 or Repetitions) await Stage(mode, i == 1 ? "first" : "repeated", i, ManagerDisposed(manager), ct);
|
||||
}
|
||||
await app.DisposeAsync().AsTask().WaitAsync(ct); app = null;
|
||||
await Stage(mode, "disposed", Repetitions, ManagerDisposed(manager), ct);
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), ct);
|
||||
await Stage(mode, "idle", Repetitions, ManagerDisposed(manager), ct);
|
||||
// Preserve managed and native post-disposal observations before any ownership assertion rejects the arm.
|
||||
Require(ManagerDisposed(manager), "Application manager not disposed");
|
||||
Require(Certificate.InstancesLeaked == 0, "SDK certificate cores remain after owner disposal");
|
||||
Require(RuntimeTemporaryKeychainCount() == 0, "Runtime tracked temporary keychain owners remain after application disposal");
|
||||
var after = Directory.GetFiles(pki, "*.der", SearchOption.AllDirectories).Where(p => p.Contains(Path.DirectorySeparatorChar + "own" + Path.DirectorySeparatorChar + "certs" + Path.DirectorySeparatorChar, StringComparison.Ordinal))
|
||||
.Select(p => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(p)))).Order().ToArray();
|
||||
Require(after.SequenceEqual(before), "Own application certificate changed");
|
||||
Console.WriteLine(JsonSerializer.Serialize(new { kind = "complete", mode, operations = Repetitions, sameLeafSha256 = expected,
|
||||
certificateUnchanged = true, managerDisposed = true, certificateCoresOutstanding = Certificate.InstancesLeaked, fullSoakGate = false }));
|
||||
}
|
||||
finally { if (app is not null) await app.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(10)); }
|
||||
}
|
||||
public static async Task<int> Main(string[] args)
|
||||
{
|
||||
Root = Path.GetFullPath(args[1]); Directory.CreateDirectory(Root);
|
||||
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(180));
|
||||
try
|
||||
{
|
||||
Require(OperatingSystem.IsMacOS(), "This control requires macOS native inventory");
|
||||
Require(Environment.Version.ToString() == "10.0.14", "Matched runtime must be .NET 10.0.14");
|
||||
if (args[0] == "seed")
|
||||
{
|
||||
await using var app = await Open(Path.Combine(Root, "pki"), DefaultTelemetry.Create(_ => { }), deadline.Token);
|
||||
using var entry = app.ApplicationConfiguration!.CertificateManager.AcquireApplicationCertificateBySecurityPolicy(SecurityPolicies.Basic256Sha256);
|
||||
Require(entry is not null, "Seed registry not populated");
|
||||
Console.WriteLine(JsonSerializer.Serialize(new { kind = "seed", leafSha256 = Hash(entry!.Certificate), runtime = Environment.Version.ToString(),
|
||||
identifierPublicProperties = typeof(CertificateIdentifier).GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(p => p.Name).Order().ToArray(),
|
||||
identifierPublicConstructors = typeof(CertificateIdentifier).GetConstructors().Select(c => c.ToString()).ToArray(),
|
||||
cryptographyRuntime = new { file = typeof(X509Certificate2).Assembly.Location,
|
||||
informationalVersion = typeof(X509Certificate2).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion,
|
||||
sha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(typeof(X509Certificate2).Assembly.Location))).ToLowerInvariant() } }));
|
||||
return 0;
|
||||
}
|
||||
Require(args[0] is "store" or "registry", "Unknown control mode");
|
||||
await Arm(args[0], deadline.Token); return 0;
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
Console.WriteLine(JsonSerializer.Serialize(new { kind = "failed", errorType = error.GetType().FullName, message = error.Message }));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:40:21: warning: 'SecKeychainGetPath' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
40 | OSStatus status=SecKeychainGetPath(keychain,&length,path);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:474:10: note: 'SecKeychainGetPath' has been explicitly marked deprecated here
|
||||
474 | OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:51:29: warning: 'SecKeychainCopyDefault' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
51 | OSStatus default_status=SecKeychainCopyDefault(&default_keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:384:10: note: 'SecKeychainCopyDefault' has been explicitly marked deprecated here
|
||||
384 | OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:55:28: warning: 'SecKeychainCopySearchList' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
55 | OSStatus search_status=SecKeychainCopySearchList(&search);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:404:10: note: 'SecKeychainCopySearchList' has been explicitly marked deprecated here
|
||||
404 | OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:94:28: warning: 'SecKeychainCreate' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
94 | OSStatus create_status=SecKeychainCreate(path,(UInt32)strlen(password),password,false,NULL,&keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:309:10: note: 'SecKeychainCreate' has been explicitly marked deprecated here
|
||||
309 | OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:103:35: warning: 'SecKeychainDelete' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
103 | if(verified)delete_status=SecKeychainDelete(keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:319:10: note: 'SecKeychainDelete' has been explicitly marked deprecated here
|
||||
319 | OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray)
|
||||
| ^
|
||||
5 warnings generated.
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"remainingOwnedKeychainFiles": 0
|
||||
}
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"ownedFixtureRootRemoved": true
|
||||
}
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"sourceSha256": "78354b154778fa61a7fe67fdef3fab6ea04ac5bdf2ae8190a2e7414781e1397d",
|
||||
"runnerSourceSha256": "1b2148f1c20578529355379ab94b439931d7241608a5d5effce8fc86f4af7bc6",
|
||||
"compileCommand": [
|
||||
"clang",
|
||||
"-std=c11",
|
||||
"-O0",
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c",
|
||||
"-framework",
|
||||
"Security",
|
||||
"-framework",
|
||||
"CoreFoundation",
|
||||
"-o",
|
||||
"/private/tmp/opcua2-pure-apple-20261110b/PureAppleControl"
|
||||
],
|
||||
"compiler": "Apple clang version 21.0.0 (clang-2100.0.123.102)\nTarget: arm64-apple-darwin25.5.0\nThread model: posix\nInstalledDir: /Library/Developer/CommandLineTools/usr/bin\n",
|
||||
"os": "ProductName:\t\tmacOS\nProductVersion:\t\t26.5.2\nBuildVersion:\t\t25F84\n",
|
||||
"architecture": "arm64",
|
||||
"repetitions": 200,
|
||||
"idleSeconds": 5,
|
||||
"stages": [
|
||||
"before",
|
||||
"first",
|
||||
"repeated",
|
||||
"idle"
|
||||
],
|
||||
"fullSoakGate": false,
|
||||
"readOnlyKeychainQueries": [
|
||||
"SecKeychainCopyDefault",
|
||||
"SecKeychainCopySearchList",
|
||||
"SecKeychainGetPath"
|
||||
],
|
||||
"doesNotCallAnyDefaultOrSearchListSetter": true,
|
||||
"binarySha256": "6c87f4394c0e51bcf26f27187628d0a867feacf9b8c7a20fb94ab42baeb1d087",
|
||||
"linkedLibraries": "/private/tmp/opcua2-pure-apple-20261110b/PureAppleControl:\n\t/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 61901.101.4)\n\t/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 4424.1.255)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1356.0.0)\n"
|
||||
}
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"exitCode": 0,
|
||||
"wallSecondsIncludingProbes": 9.287588333012536,
|
||||
"samples": [
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "pure-apple",
|
||||
"stage": "before",
|
||||
"operations": 0,
|
||||
"processId": 93020,
|
||||
"utc": "2026-11-10T21:47:09.322Z",
|
||||
"elapsedSeconds": 0.004359,
|
||||
"rssBytes": 7372800,
|
||||
"createdRefs": 0,
|
||||
"releasedRefs": 0,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "pure-apple",
|
||||
"stage": "first",
|
||||
"operations": 1,
|
||||
"processId": 93020,
|
||||
"utc": "2026-11-10T21:47:10.311Z",
|
||||
"elapsedSeconds": 0.993379,
|
||||
"rssBytes": 8028160,
|
||||
"createdRefs": 1,
|
||||
"releasedRefs": 1,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "pure-apple",
|
||||
"stage": "repeated",
|
||||
"operations": 200,
|
||||
"processId": 93020,
|
||||
"utc": "2026-11-10T21:47:11.859Z",
|
||||
"elapsedSeconds": 2.541567,
|
||||
"rssBytes": 8699904,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "pure-apple",
|
||||
"stage": "idle",
|
||||
"operations": 200,
|
||||
"processId": 93020,
|
||||
"utc": "2026-11-10T21:47:17.582Z",
|
||||
"elapsedSeconds": 8.264326,
|
||||
"rssBytes": 8699904,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"managedRuntimePresent": false,
|
||||
"AppleDatabaseCount": 1,
|
||||
"AppleDatabaseShallowBytes": 768,
|
||||
"AppleDatabaseClassAbsent": false,
|
||||
"databaseManagerClassPresent": true,
|
||||
"fdCount": 3,
|
||||
"ownedTemporaryFdCount": 0,
|
||||
"ownedKeychainFdCount": 0,
|
||||
"ownedKeychainFileCount": 0
|
||||
}
|
||||
],
|
||||
"fingerprints": [
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "before",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 2
|
||||
},
|
||||
{
|
||||
"kind": "fingerprint",
|
||||
"stage": "after",
|
||||
"defaultStatus": 0,
|
||||
"defaultPathStatus": 0,
|
||||
"searchStatus": 0,
|
||||
"searchPathStatus": 0,
|
||||
"defaultSha256": "08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63",
|
||||
"searchSha256": "c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c",
|
||||
"searchCount": 2,
|
||||
"ownedQueryReferencesReleased": 4
|
||||
}
|
||||
],
|
||||
"complete": {
|
||||
"kind": "complete",
|
||||
"operations": 200,
|
||||
"createdRefs": 200,
|
||||
"releasedRefs": 200,
|
||||
"readOnlyDefaultAndSearchListUnchanged": true,
|
||||
"elapsedSeconds": 8.994713,
|
||||
"fullSoakGate": false
|
||||
},
|
||||
"fullSoakGate": false,
|
||||
"nativeInventoryIsNotOpenHandlesOrExclusiveRss": true,
|
||||
"nativeDeleteOsStatusesAllZero": true
|
||||
}
|
||||
-207
@@ -1,207 +0,0 @@
|
||||
{"kind":"fingerprint","stage":"before","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":2}
|
||||
{"kind":"checkpoint","mode":"pure-apple","stage":"before","operations":0,"processId":93020,"utc":"2026-11-10T21:47:09.322Z","elapsedSeconds":0.004359,"rssBytes":7372800,"createdRefs":0,"releasedRefs":0,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":1,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"checkpoint","mode":"pure-apple","stage":"first","operations":1,"processId":93020,"utc":"2026-11-10T21:47:10.311Z","elapsedSeconds":0.993379,"rssBytes":8028160,"createdRefs":1,"releasedRefs":1,"managedRuntimePresent":false}
|
||||
{"kind":"operation","iteration":2,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":3,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":4,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":5,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":6,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":7,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":8,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":9,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":10,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":11,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":12,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":13,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":14,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":15,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":16,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":17,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":18,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":19,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":20,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":21,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":22,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":23,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":24,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":25,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":26,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":27,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":28,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":29,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":30,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":31,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":32,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":33,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":34,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":35,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":36,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":37,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":38,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":39,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":40,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":41,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":42,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":43,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":44,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":45,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":46,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":47,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":48,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":49,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":50,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":51,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":52,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":53,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":54,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":55,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":56,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":57,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":58,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":59,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":60,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":61,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":62,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":63,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":64,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":65,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":66,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":67,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":68,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":69,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":70,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":71,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":72,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":73,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":74,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":75,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":76,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":77,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":78,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":79,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":80,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":81,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":82,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":83,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":84,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":85,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":86,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":87,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":88,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":89,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":90,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":91,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":92,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":93,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":94,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":95,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":96,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":97,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":98,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":99,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":100,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":101,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":102,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":103,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":104,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":105,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":106,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":107,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":108,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":109,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":110,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":111,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":112,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":113,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":114,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":115,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":116,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":117,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":118,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":119,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":120,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":121,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":122,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":123,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":124,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":125,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":126,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":127,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":128,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":129,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":130,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":131,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":132,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":133,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":134,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":135,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":136,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":137,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":138,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":139,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":140,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":141,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":142,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":143,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":144,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":145,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":146,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":147,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":148,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":149,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":150,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":151,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":152,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":153,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":154,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":155,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":156,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":157,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":158,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":159,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":160,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":161,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":162,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":163,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":164,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":165,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":166,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":167,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":168,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":169,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":170,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":171,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":172,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":173,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":174,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":175,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":176,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":177,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":178,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":179,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":180,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":181,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":182,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":183,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":184,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":185,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":186,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":187,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":188,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":189,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":190,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":191,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":192,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":193,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":194,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":195,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":196,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":197,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":198,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":199,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"operation","iteration":200,"createStatus":0,"pathStatus":0,"deleteStatus":0,"returnedRef":true,"privatePathVerified":true,"releasedExactlyOnce":true}
|
||||
{"kind":"checkpoint","mode":"pure-apple","stage":"repeated","operations":200,"processId":93020,"utc":"2026-11-10T21:47:11.859Z","elapsedSeconds":2.541567,"rssBytes":8699904,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"fingerprint","stage":"after","defaultStatus":0,"defaultPathStatus":0,"searchStatus":0,"searchPathStatus":0,"defaultSha256":"08c2c77dd8eaf8042b4020991ea06c6215cc391532869bbf6ced2cf1126c5e63","searchSha256":"c05fae700986dc7a6a147a938ef2adc4a274173420e137929ed58ad986eb2a3c","searchCount":2,"ownedQueryReferencesReleased":4}
|
||||
{"kind":"checkpoint","mode":"pure-apple","stage":"idle","operations":200,"processId":93020,"utc":"2026-11-10T21:47:17.582Z","elapsedSeconds":8.264326,"rssBytes":8699904,"createdRefs":200,"releasedRefs":200,"managedRuntimePresent":false}
|
||||
{"kind":"complete","operations":200,"createdRefs":200,"releasedRefs":200,"readOnlyDefaultAndSearchListUnchanged":true,"elapsedSeconds":8.994713,"fullSoakGate":false}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:36:21: warning: 'SecKeychainGetPath' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
36 | OSStatus status=SecKeychainGetPath(keychain,&length,path);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:474:10: note: 'SecKeychainGetPath' has been explicitly marked deprecated here
|
||||
474 | OSStatus SecKeychainGetPath(SecKeychainRef __nullable keychain, UInt32 *ioPathLength, char *pathName)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:47:29: warning: 'SecKeychainCopyDefault' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
47 | OSStatus default_status=SecKeychainCopyDefault(&default_keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:384:10: note: 'SecKeychainCopyDefault' has been explicitly marked deprecated here
|
||||
384 | OSStatus SecKeychainCopyDefault(SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:51:28: warning: 'SecKeychainCopySearchList' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
51 | OSStatus search_status=SecKeychainCopySearchList(&search);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:404:10: note: 'SecKeychainCopySearchList' has been explicitly marked deprecated here
|
||||
404 | OSStatus SecKeychainCopySearchList(CFArrayRef * __nonnull CF_RETURNS_RETAINED searchList)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:84:83: error: call to undeclared function 'explicit_bzero'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
|
||||
84 | char suffix[33],password[65];hex(random,16,suffix);hex(random+16,32,password);explicit_bzero(random,sizeof(random));
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:90:28: warning: 'SecKeychainCreate' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
90 | OSStatus create_status=SecKeychainCreate(path,(UInt32)strlen(password),password,false,NULL,&keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:309:10: note: 'SecKeychainCreate' has been explicitly marked deprecated here
|
||||
309 | OSStatus SecKeychainCreate(const char *pathName, UInt32 passwordLength, const void * __nullable password, Boolean promptUser, SecAccessRef __nullable initialAccess, SecKeychainRef * __nonnull CF_RETURNS_RETAINED keychain)
|
||||
| ^
|
||||
<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c:99:35: warning: 'SecKeychainDelete' is deprecated: first deprecated in macOS 10.10 - SecKeychain is deprecated [-Wdeprecated-declarations]
|
||||
99 | if(verified)delete_status=SecKeychainDelete(keychain);
|
||||
| ^
|
||||
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Security.framework/Headers/SecKeychain.h:319:10: note: 'SecKeychainDelete' has been explicitly marked deprecated here
|
||||
319 | OSStatus SecKeychainDelete(SecKeychainRef __nullable keychainOrArray)
|
||||
| ^
|
||||
5 warnings and 1 error generated.
|
||||
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"compileExitCode": 1,
|
||||
"nativeProcessNeverStarted": true,
|
||||
"emptyOwnedFixtureRootRemoved": true
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
{
|
||||
"sourceSha256": "f3d5b393f4bfcb350b37d610a8b6602b480e573e632f697b311813df276be347",
|
||||
"runnerSourceSha256": "22f0ee93b2998f1cb337aa5f763dcf578b2efe4616502ad095a309cc774c3c76",
|
||||
"compileCommand": [
|
||||
"clang",
|
||||
"-std=c11",
|
||||
"-O0",
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"<user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/scripts/validation/opcua-lifecycle-memory/native-retention/PureAppleControl.c",
|
||||
"-framework",
|
||||
"Security",
|
||||
"-framework",
|
||||
"CoreFoundation",
|
||||
"-o",
|
||||
"/private/tmp/opcua2-pure-apple-20261110a/PureAppleControl"
|
||||
],
|
||||
"compiler": "Apple clang version 21.0.0 (clang-2100.0.123.102)\nTarget: arm64-apple-darwin25.5.0\nThread model: posix\nInstalledDir: /Library/Developer/CommandLineTools/usr/bin\n",
|
||||
"os": "ProductName:\t\tmacOS\nProductVersion:\t\t26.5.2\nBuildVersion:\t\t25F84\n",
|
||||
"architecture": "arm64",
|
||||
"repetitions": 200,
|
||||
"idleSeconds": 5,
|
||||
"stages": [
|
||||
"before",
|
||||
"first",
|
||||
"repeated",
|
||||
"idle"
|
||||
],
|
||||
"fullSoakGate": false,
|
||||
"readOnlyKeychainQueries": [
|
||||
"SecKeychainCopyDefault",
|
||||
"SecKeychainCopySearchList",
|
||||
"SecKeychainGetPath"
|
||||
],
|
||||
"doesNotCallAnyDefaultOrSearchListSetter": true
|
||||
}
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
{
|
||||
"actualNativeExecutions": 1,
|
||||
"earlierAttemptWasCompileOnly": true,
|
||||
"rawActualOutput": "/tmp/opcua2-pure-apple-20261110b",
|
||||
"rawCompileOnlyOutput": "/tmp/opcua2-pure-apple-20261110a",
|
||||
"rawSha256": {
|
||||
"actual-run-result.json": "70b7f3c57a5d14baf9cc593c16670da85adcb525e5f60bb419c8f0f01e206347",
|
||||
"actual-run-provenance.json": "aa181c0213588aede6d20888ede49ef2a74bb409c075d90a6bad214cfbdac29f",
|
||||
"actual-run-samples.jsonl": "4ebb9870e0e66d1a217ce489058a1658b0be71a5928115bbf347478bc1e6066a",
|
||||
"actual-run-build.log": "786ee9f813146b634d814e1cdb8f35fe1d9ef88a9ea96265bc3ffdafe4c61b6e",
|
||||
"actual-run-fixture-before-harness-cleanup.json": "eaaf36a5e7f7d1d3635e987d8f9a2600ce55f6482011ec9a7abf3e4dd759d9c4",
|
||||
"actual-run-fixture-cleanup.json": "1785d6ee67b2f7e77037a469ca2bdb9b07c8892781ea830a985f6ef505f84d69",
|
||||
"first-build-only-build.log": "ebaa2a34424167053a50f410ee04c6ed0988566c5c68e7c2473a55579baf1818",
|
||||
"first-build-only-provenance.json": "7236bb169732e2fe03d78af2691be3d41632bf1e9a79902ae74aa0ed4c6a539b",
|
||||
"first-build-only-fixture-cleanup.json": "e5551f93e5a2d898cf35b59f775ef8b6fecc06c673680cf8486019e73b44866f"
|
||||
},
|
||||
"redaction": "Selected text replaces only the local home prefix; raw receipts were not modified.",
|
||||
"review": "Astra independently verified all207 rows,200 ordered operations/status triples, reference balance, fingerprints, all4 native counts/bytes, FD/file counts, hashes, cleanup and5 unsuppressed warnings.",
|
||||
"retentionReproducedByEmptyNativeLifecycle": false,
|
||||
"fullSoakGate": false
|
||||
}
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
Determining projects to restore...
|
||||
Restored /private/tmp/opcua2-native-reload-20261110a/Control.csproj (in 34 ms).
|
||||
Control -> /private/tmp/opcua2-native-reload-20261110a/bin/Release/net10.0/Control.dll
|
||||
|
||||
Build succeeded.
|
||||
0 Warning(s)
|
||||
0 Error(s)
|
||||
|
||||
Time Elapsed 00:00:00.63
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"allOwnedFixtureDirectoriesRemoved": true
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"controlSourceSha256": "e8c959a076bf1eecaad7e1ae71d8df3c2c86d2978a4558c98792471e880efc27",
|
||||
"runnerSourceSha256": "159ba76b3048d1a594e3a28032d350e36bc8ead4c93c525c5a60b3013699aeef",
|
||||
"repetitionsPerArm": 200,
|
||||
"stages": [
|
||||
"ready",
|
||||
"first",
|
||||
"repeated",
|
||||
"disposed",
|
||||
"idle"
|
||||
],
|
||||
"idleSeconds": 5,
|
||||
"fullSoakGate": false,
|
||||
"leakTracking": true,
|
||||
"trackingOverhead": "Both A/B processes capture allocation stacks; additional allocation and GC overhead is included in observed memory.",
|
||||
"nativeReferences": {
|
||||
"Opc.Ua.Client.dll": "620da406fabdbc75d11f9827ea7e39d2d3c762471bd2264b0d11f1d6cd9247cd",
|
||||
"Opc.Ua.Configuration.dll": "6ed6a594c93c3ff35d1a16539a9fe87c1e2640549cc2f48ed6bae333dc8bf0e7",
|
||||
"Opc.Ua.Core.Schema.dll": "51cfad48657d95d38074bb88be29aea6f5b361a07397247d58838d066b99772e",
|
||||
"Opc.Ua.Core.Types.dll": "a7dd141b8dabe8848ff28c2fb8e16a85a0508e6a49e6b1a1c1e267175b99af96",
|
||||
"Opc.Ua.Core.dll": "9d0857aa6b7f3c49037d4ea557b4da8edf07e146069464481783e66c5c9cd35a",
|
||||
"Opc.Ua.Security.Certificates.dll": "7f4969aceb2f0db5328c6882cb4b117342f3b18905c38acdba600683860c4fd0",
|
||||
"Opc.Ua.Server.dll": "930e714a2f6e15d393840bcdc95e1afa8012bc740c3738a655f958142721864e",
|
||||
"Opc.Ua.Types.dll": "c542f69882f4e8a4ebd5ccc28a3881d6967c7ffb6dcc3c56dc6c776f39c2ede1"
|
||||
},
|
||||
"hostDotnet": ".NET SDK:\n Version: 10.0.403\n Commit: 5a2162bea6\n Workload version: 10.0.400-manifests.a00bebb6\n MSBuild version: 18.9.15+5a2162bea\n\nRuntime Environment:\n OS Name: Mac OS X\n OS Version: 26.5\n OS Platform: Darwin\n RID: osx-arm64\n Base Path: /opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk/10.0.403/\n\n.NET workloads installed:\nThere are no installed workloads to display.\nConfigured to use workload sets when installing new manifests.\nNo workload sets are installed. Run \"dotnet workload restore\" to install a workload set.\n\nHost:\n Version: 10.0.14\n Architecture: arm64\n Commit: 0427b9abbe\n\n.NET SDKs installed:\n 10.0.403 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/sdk]\n\n.NET runtimes installed:\n Microsoft.AspNetCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.AspNetCore.App]\n Microsoft.NETCore.App 10.0.14 [/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App]\n\nOther architectures found:\n None\n\nEnvironment variables:\n DOTNET_ROOT [/opt/homebrew/Cellar/dotnet/10.0.403/libexec]\n\nglobal.json file:\n <user-home>/.codex/worktrees/opcua2-client-lifecycle/OtOpcUa/global.json\n\nLearn more:\n https://aka.ms/dotnet/info\n\nDownload .NET:\n https://aka.ms/dotnet/download\n",
|
||||
"os": "ProductName:\t\tmacOS\nProductVersion:\t\t26.5.2\nBuildVersion:\t\t25F84\n",
|
||||
"architecture": "arm64",
|
||||
"cryptographyRuntime": {
|
||||
"file": "/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App/10.0.14/System.Security.Cryptography.dll",
|
||||
"informationalVersion": "10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa",
|
||||
"sha256": "f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{"kind":"checkpoint","mode":"registry","stage":"ready","operations":0,"processId":55851,"utc":"2026-11-10T21:30:30.043224+00:00","managerDisposed":false,"managedBytes":831128,"rssBytes":87654400,"privateBytes":0,"allocatedBytes":1761744,"compiledMethods":1192,"gc":[2,2,2],"certificateCoresCreated":7,"certificateCoresDisposed":6,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"registry","stage":"first","operations":1,"processId":55851,"utc":"2026-11-10T21:30:31.093095+00:00","managerDisposed":false,"managedBytes":1055944,"rssBytes":91095040,"privateBytes":0,"allocatedBytes":2051888,"compiledMethods":1777,"gc":[4,4,4],"certificateCoresCreated":7,"certificateCoresDisposed":6,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"registry","stage":"repeated","operations":200,"processId":55851,"utc":"2026-11-10T21:30:32.143169+00:00","managerDisposed":false,"managedBytes":1098664,"rssBytes":97779712,"privateBytes":0,"allocatedBytes":7937936,"compiledMethods":2093,"gc":[6,6,6],"certificateCoresCreated":7,"certificateCoresDisposed":6,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"registry","stage":"disposed","operations":200,"processId":55851,"utc":"2026-11-10T21:30:33.170061+00:00","managerDisposed":true,"managedBytes":1104720,"rssBytes":97927168,"privateBytes":0,"allocatedBytes":7949840,"compiledMethods":2207,"gc":[8,8,8],"certificateCoresCreated":7,"certificateCoresDisposed":7,"certificateCoresOutstanding":0,"runtimeTrackedTemporaryKeychains":0}
|
||||
{"kind":"checkpoint","mode":"registry","stage":"idle","operations":200,"processId":55851,"utc":"2026-11-10T21:30:39.166632+00:00","managerDisposed":true,"managedBytes":1130616,"rssBytes":97927168,"privateBytes":0,"allocatedBytes":7966976,"compiledMethods":2251,"gc":[10,10,10],"certificateCoresCreated":7,"certificateCoresDisposed":7,"certificateCoresOutstanding":0,"runtimeTrackedTemporaryKeychains":0}
|
||||
{"kind":"complete","mode":"registry","operations":200,"sameLeafSha256":"fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2","certificateUnchanged":true,"managerDisposed":true,"certificateCoresOutstanding":0,"fullSoakGate":false}
|
||||
-366
@@ -1,366 +0,0 @@
|
||||
{
|
||||
"status": "passed",
|
||||
"seed": {
|
||||
"kind": "seed",
|
||||
"leafSha256": "fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2",
|
||||
"runtime": "10.0.14",
|
||||
"identifierPublicProperties": [
|
||||
"BinaryEncodingId",
|
||||
"CertificateType",
|
||||
"CertificateTypeString",
|
||||
"RawData",
|
||||
"StorePath",
|
||||
"StoreType",
|
||||
"SubjectName",
|
||||
"Thumbprint",
|
||||
"TypeId",
|
||||
"ValidationOptions",
|
||||
"XmlEncodingId"
|
||||
],
|
||||
"identifierPublicConstructors": [
|
||||
"Void .ctor()"
|
||||
],
|
||||
"cryptographyRuntime": {
|
||||
"file": "/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App/10.0.14/System.Security.Cryptography.dll",
|
||||
"informationalVersion": "10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa",
|
||||
"sha256": "f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"
|
||||
}
|
||||
},
|
||||
"arms": {
|
||||
"store": {
|
||||
"exitCode": 0,
|
||||
"complete": {
|
||||
"kind": "complete",
|
||||
"mode": "store",
|
||||
"operations": 200,
|
||||
"sameLeafSha256": "fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2",
|
||||
"certificateUnchanged": true,
|
||||
"managerDisposed": true,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"fullSoakGate": false
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "store",
|
||||
"stage": "ready",
|
||||
"operations": 0,
|
||||
"processId": 54422,
|
||||
"utc": "2026-11-10T21:30:07.200103+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 831080,
|
||||
"rssBytes": 87621632,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 1786744,
|
||||
"compiledMethods": 1192,
|
||||
"gc": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 6,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 110,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "store",
|
||||
"stage": "first",
|
||||
"operations": 1,
|
||||
"processId": 54422,
|
||||
"utc": "2026-11-10T21:30:10.186803+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 1112360,
|
||||
"rssBytes": 91619328,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 2248768,
|
||||
"compiledMethods": 2073,
|
||||
"gc": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
],
|
||||
"certificateCoresCreated": 9,
|
||||
"certificateCoresDisposed": 8,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 4,
|
||||
"AppleDatabaseShallowBytes": 3072,
|
||||
"fdCount": 110,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "store",
|
||||
"stage": "repeated",
|
||||
"operations": 200,
|
||||
"processId": 54422,
|
||||
"utc": "2026-11-10T21:30:21.723766+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 1191400,
|
||||
"rssBytes": 115097600,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 31247912,
|
||||
"compiledMethods": 4552,
|
||||
"gc": [
|
||||
9,
|
||||
6,
|
||||
6
|
||||
],
|
||||
"certificateCoresCreated": 407,
|
||||
"certificateCoresDisposed": 406,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 203,
|
||||
"AppleDatabaseShallowBytes": 155904,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "store",
|
||||
"stage": "disposed",
|
||||
"operations": 200,
|
||||
"processId": 54422,
|
||||
"utc": "2026-11-10T21:30:22.710567+00:00",
|
||||
"managerDisposed": true,
|
||||
"managedBytes": 1196408,
|
||||
"rssBytes": 115212288,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 31265712,
|
||||
"compiledMethods": 4618,
|
||||
"gc": [
|
||||
11,
|
||||
8,
|
||||
8
|
||||
],
|
||||
"certificateCoresCreated": 407,
|
||||
"certificateCoresDisposed": 407,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"runtimeTrackedTemporaryKeychains": 0,
|
||||
"AppleDatabaseCount": 203,
|
||||
"AppleDatabaseShallowBytes": 155904,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "store",
|
||||
"stage": "idle",
|
||||
"operations": 200,
|
||||
"processId": 54422,
|
||||
"utc": "2026-11-10T21:30:28.704218+00:00",
|
||||
"managerDisposed": true,
|
||||
"managedBytes": 1222192,
|
||||
"rssBytes": 115130368,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 31283272,
|
||||
"compiledMethods": 4638,
|
||||
"gc": [
|
||||
13,
|
||||
10,
|
||||
10
|
||||
],
|
||||
"certificateCoresCreated": 407,
|
||||
"certificateCoresDisposed": 407,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"runtimeTrackedTemporaryKeychains": 0,
|
||||
"AppleDatabaseCount": 203,
|
||||
"AppleDatabaseShallowBytes": 155904,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 0
|
||||
}
|
||||
],
|
||||
"nativeCountIsNotOpenHandleOrExclusiveRssAttribution": true,
|
||||
"registryArmIsNotApprovedProductionMitigation": true
|
||||
},
|
||||
"registry": {
|
||||
"exitCode": 0,
|
||||
"complete": {
|
||||
"kind": "complete",
|
||||
"mode": "registry",
|
||||
"operations": 200,
|
||||
"sameLeafSha256": "fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2",
|
||||
"certificateUnchanged": true,
|
||||
"managerDisposed": true,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"fullSoakGate": false
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "registry",
|
||||
"stage": "ready",
|
||||
"operations": 0,
|
||||
"processId": 55851,
|
||||
"utc": "2026-11-10T21:30:30.043224+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 831128,
|
||||
"rssBytes": 87654400,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 1761744,
|
||||
"compiledMethods": 1192,
|
||||
"gc": [
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 6,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 110,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "registry",
|
||||
"stage": "first",
|
||||
"operations": 1,
|
||||
"processId": 55851,
|
||||
"utc": "2026-11-10T21:30:31.093095+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 1055944,
|
||||
"rssBytes": 91095040,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 2051888,
|
||||
"compiledMethods": 1777,
|
||||
"gc": [
|
||||
4,
|
||||
4,
|
||||
4
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 6,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 110,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "registry",
|
||||
"stage": "repeated",
|
||||
"operations": 200,
|
||||
"processId": 55851,
|
||||
"utc": "2026-11-10T21:30:32.143169+00:00",
|
||||
"managerDisposed": false,
|
||||
"managedBytes": 1098664,
|
||||
"rssBytes": 97779712,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 7937936,
|
||||
"compiledMethods": 2093,
|
||||
"gc": [
|
||||
6,
|
||||
6,
|
||||
6
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 6,
|
||||
"certificateCoresOutstanding": 1,
|
||||
"runtimeTrackedTemporaryKeychains": 1,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 1
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "registry",
|
||||
"stage": "disposed",
|
||||
"operations": 200,
|
||||
"processId": 55851,
|
||||
"utc": "2026-11-10T21:30:33.170061+00:00",
|
||||
"managerDisposed": true,
|
||||
"managedBytes": 1104720,
|
||||
"rssBytes": 97927168,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 7949840,
|
||||
"compiledMethods": 2207,
|
||||
"gc": [
|
||||
8,
|
||||
8,
|
||||
8
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 7,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"runtimeTrackedTemporaryKeychains": 0,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 0
|
||||
},
|
||||
{
|
||||
"kind": "checkpoint",
|
||||
"mode": "registry",
|
||||
"stage": "idle",
|
||||
"operations": 200,
|
||||
"processId": 55851,
|
||||
"utc": "2026-11-10T21:30:39.166632+00:00",
|
||||
"managerDisposed": true,
|
||||
"managedBytes": 1130616,
|
||||
"rssBytes": 97927168,
|
||||
"privateBytes": 0,
|
||||
"allocatedBytes": 7966976,
|
||||
"compiledMethods": 2251,
|
||||
"gc": [
|
||||
10,
|
||||
10,
|
||||
10
|
||||
],
|
||||
"certificateCoresCreated": 7,
|
||||
"certificateCoresDisposed": 7,
|
||||
"certificateCoresOutstanding": 0,
|
||||
"runtimeTrackedTemporaryKeychains": 0,
|
||||
"AppleDatabaseCount": 3,
|
||||
"AppleDatabaseShallowBytes": 2304,
|
||||
"fdCount": 112,
|
||||
"pkiFdCount": 0,
|
||||
"temporaryDirectoryFdCount": 1,
|
||||
"temporaryKeychainFdCount": 0,
|
||||
"temporaryKeychainFileCount": 0
|
||||
}
|
||||
],
|
||||
"nativeCountIsNotOpenHandleOrExclusiveRssAttribution": true,
|
||||
"registryArmIsNotApprovedProductionMitigation": true
|
||||
}
|
||||
},
|
||||
"fullSoakGate": false
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"kind":"seed","leafSha256":"fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2","runtime":"10.0.14","identifierPublicProperties":["BinaryEncodingId","CertificateType","CertificateTypeString","RawData","StorePath","StoreType","SubjectName","Thumbprint","TypeId","ValidationOptions","XmlEncodingId"],"identifierPublicConstructors":["Void .ctor()"],"cryptographyRuntime":{"file":"/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App/10.0.14/System.Security.Cryptography.dll","informationalVersion":"10.0.14\u002B0427b9abbead3fa64c6655eb4290c537397131fa","sha256":"f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"}}
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
{
|
||||
"sdkCommit": "07e62f72500cc0923a2bab940653c8c1116fa286",
|
||||
"sdkCheckoutDirty": "",
|
||||
"files": [
|
||||
{
|
||||
"path": "src/Opc.Ua.Client/Session/DefaultSessionFactory.cs",
|
||||
"sha256": "366481e7f75fdaae48e2b35574a1624c685b2ae7f004c1c0204068465a737e3c"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Client/Session/Session.cs",
|
||||
"sha256": "2af9a217a37ec35c99244983a0896277fbec616f4656e68ce9be03356b3a3f20"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Security/Certificates/CertificateIdentifierResolver.cs",
|
||||
"sha256": "2593c29171e83f8536c2923c9f8a394fadfc738a78532743dd7c1d07c6e7915f"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Security/Certificates/DirectoryCertificateStore.cs",
|
||||
"sha256": "490b75486ef3278ae6400b1ff47437b0557254ce0d0eff29ff9ebe2f29d50650"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Security/Certificates/SecurityConfiguration.cs",
|
||||
"sha256": "76222952f07c4cf97326132103684ede51bea46c43dae5f7ca1228f62255ae43"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Schema/ApplicationConfiguration.cs",
|
||||
"sha256": "0204d16915e317360f922801b59da7be03dafefe11e68672926b25e9e349db22"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Stack/Configuration/ApplicationConfiguration.cs",
|
||||
"sha256": "119b5c809154291451cfe6e4ae7b4a0c2b838e12f28231c1ac4a876a29e3efc6"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Stack/Server/ServerBase.cs",
|
||||
"sha256": "b5ba516728998b421b2573316deafbbe774792af99a10558ed0843505b5d3a09"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Core/Security/Certificates/CertificateManager/CertificateManager.cs",
|
||||
"sha256": "e63a56b4e2cf1183e73737da925ee5f7da3d7c291ecaea361d9ddc6e58ea1695"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Configuration/ApplicationInstance.cs",
|
||||
"sha256": "b6186e78effbc2301725914098cde8bd948ddce3147ce756b703fd76db1d32b3"
|
||||
},
|
||||
{
|
||||
"path": "src/Opc.Ua.Security.Certificates/X509Certificate/Certificate.cs",
|
||||
"sha256": "6f0be22e80e05607d1c3e35ce0fe218273446c397c18df909124be61ee437f56"
|
||||
},
|
||||
{
|
||||
"path": "tests/Opc.Ua.Client.Tests/Session/SessionCertificateRotationRegressionTests.cs",
|
||||
"sha256": "ad904d541ee2f0a08af44ba1ad58eda3db1be19305c3bab43f476fe2c0d71ae6"
|
||||
}
|
||||
]
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
{"kind":"checkpoint","mode":"store","stage":"ready","operations":0,"processId":54422,"utc":"2026-11-10T21:30:07.200103+00:00","managerDisposed":false,"managedBytes":831080,"rssBytes":87621632,"privateBytes":0,"allocatedBytes":1786744,"compiledMethods":1192,"gc":[2,2,2],"certificateCoresCreated":7,"certificateCoresDisposed":6,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"store","stage":"first","operations":1,"processId":54422,"utc":"2026-11-10T21:30:10.186803+00:00","managerDisposed":false,"managedBytes":1112360,"rssBytes":91619328,"privateBytes":0,"allocatedBytes":2248768,"compiledMethods":2073,"gc":[4,4,4],"certificateCoresCreated":9,"certificateCoresDisposed":8,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"store","stage":"repeated","operations":200,"processId":54422,"utc":"2026-11-10T21:30:21.723766+00:00","managerDisposed":false,"managedBytes":1191400,"rssBytes":115097600,"privateBytes":0,"allocatedBytes":31247912,"compiledMethods":4552,"gc":[9,6,6],"certificateCoresCreated":407,"certificateCoresDisposed":406,"certificateCoresOutstanding":1,"runtimeTrackedTemporaryKeychains":1}
|
||||
{"kind":"checkpoint","mode":"store","stage":"disposed","operations":200,"processId":54422,"utc":"2026-11-10T21:30:22.710567+00:00","managerDisposed":true,"managedBytes":1196408,"rssBytes":115212288,"privateBytes":0,"allocatedBytes":31265712,"compiledMethods":4618,"gc":[11,8,8],"certificateCoresCreated":407,"certificateCoresDisposed":407,"certificateCoresOutstanding":0,"runtimeTrackedTemporaryKeychains":0}
|
||||
{"kind":"checkpoint","mode":"store","stage":"idle","operations":200,"processId":54422,"utc":"2026-11-10T21:30:28.704218+00:00","managerDisposed":true,"managedBytes":1222192,"rssBytes":115130368,"privateBytes":0,"allocatedBytes":31283272,"compiledMethods":4638,"gc":[13,10,10],"certificateCoresCreated":407,"certificateCoresDisposed":407,"certificateCoresOutstanding":0,"runtimeTrackedTemporaryKeychains":0}
|
||||
{"kind":"complete","mode":"store","operations":200,"sameLeafSha256":"fadcc11ec694732b82fe4dc47bb41bce6023d113339e53aca9fee5b079f200b2","certificateUnchanged":true,"managerDisposed":true,"certificateCoresOutstanding":0,"fullSoakGate":false}
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
{
|
||||
"purpose": "attribution-only, not a production mitigation or full soak",
|
||||
"controlRunsPerArm": 1,
|
||||
"sourceCommit": "ed60970fc294ab171a80cda1b57942a7130b4c39",
|
||||
"sdkSourceCommit": "07e62f72500cc0923a2bab940653c8c1116fa286",
|
||||
"rawArtifacts": "/private/tmp/opcua2-native-reload-20261110a",
|
||||
"artifactCreationToFinalResultWriteWallSeconds": 34.69896697998047,
|
||||
"wallIntervalIsFilesystemBasedNotMonotonicGate": true,
|
||||
"sdkFileHashes": {
|
||||
"Opc.Ua.Client.dll": "620da406fabdbc75d11f9827ea7e39d2d3c762471bd2264b0d11f1d6cd9247cd",
|
||||
"Opc.Ua.Configuration.dll": "6ed6a594c93c3ff35d1a16539a9fe87c1e2640549cc2f48ed6bae333dc8bf0e7",
|
||||
"Opc.Ua.Core.Schema.dll": "51cfad48657d95d38074bb88be29aea6f5b361a07397247d58838d066b99772e",
|
||||
"Opc.Ua.Core.Types.dll": "a7dd141b8dabe8848ff28c2fb8e16a85a0508e6a49e6b1a1c1e267175b99af96",
|
||||
"Opc.Ua.Core.dll": "9d0857aa6b7f3c49037d4ea557b4da8edf07e146069464481783e66c5c9cd35a",
|
||||
"Opc.Ua.Security.Certificates.dll": "7f4969aceb2f0db5328c6882cb4b117342f3b18905c38acdba600683860c4fd0",
|
||||
"Opc.Ua.Server.dll": "930e714a2f6e15d393840bcdc95e1afa8012bc740c3738a655f958142721864e",
|
||||
"Opc.Ua.Types.dll": "c542f69882f4e8a4ebd5ccc28a3881d6967c7ffb6dcc3c56dc6c776f39c2ede1"
|
||||
},
|
||||
"installedCryptography": {
|
||||
"file": "/opt/homebrew/Cellar/dotnet/10.0.403/libexec/shared/Microsoft.NETCore.App/10.0.14/System.Security.Cryptography.dll",
|
||||
"informationalVersion": "10.0.14+0427b9abbead3fa64c6655eb4290c537397131fa",
|
||||
"sha256": "f4957d7218a004a27bf8964e45147df6a88092c6e7344582082840d62c6c579a"
|
||||
},
|
||||
"checkpointIntervals": {
|
||||
"store": {
|
||||
"readyToIdleWallSeconds": 21.504115,
|
||||
"readyUtc": "2026-11-10T21:30:07.200103+00:00",
|
||||
"idleUtc": "2026-11-10T21:30:28.704218+00:00"
|
||||
},
|
||||
"registry": {
|
||||
"readyToIdleWallSeconds": 9.123408,
|
||||
"readyUtc": "2026-11-10T21:30:30.043224+00:00",
|
||||
"idleUtc": "2026-11-10T21:30:39.166632+00:00"
|
||||
}
|
||||
},
|
||||
"installedRuntimeDecompile": {
|
||||
"temporaryKeychainHandle": {
|
||||
"localPath": "/tmp/opcua2-native-runtime-keychain-decompiled.cs",
|
||||
"sha256": "96c2e996638ffdd17c35483aaece7fdbc499fd004ab549e2e128bf82a64b5dc2",
|
||||
"tool": "ilspycmd 10.1.0.8386",
|
||||
"readOnly": true
|
||||
},
|
||||
"certificateLoader": {
|
||||
"localPath": "/tmp/opcua2-native-runtime-loader-decompiled.cs",
|
||||
"sha256": "89434500d1723f419e83ff45fcb6e44e73b58847f4201265613587ad82a79424",
|
||||
"tool": "ilspycmd 10.1.0.8386",
|
||||
"readOnly": true
|
||||
},
|
||||
"baseKeychainHandle": {
|
||||
"localPath": "/tmp/opcua2-native-runtime-keychain-base-decompiled.cs",
|
||||
"sha256": "6f2abdb5779646a9bfd589d8fc765cab2e0290edee8396b2c7b2e6a4470e2bb4",
|
||||
"tool": "ilspycmd 10.1.0.8386",
|
||||
"readOnly": true
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"reviewer": "Astra independent security/ownership gate",
|
||||
"preExecutionCodeApproved": true,
|
||||
"postExecutionRawHeapAndHashReviewAccepted": true,
|
||||
"productionMitigationApproved": false,
|
||||
"scope": "one fixed 200-acquisition run per arm; no public upstream post or production patch"
|
||||
},
|
||||
"rawProvenanceSha256": "2bd55b5eddef09f7e4e2fcaab91c98649e62abc084565f88755ceba9eed29bfb",
|
||||
"selectedProvenanceProjection": {
|
||||
"redactedFields": [
|
||||
"hostDotnet local home prefix"
|
||||
],
|
||||
"sha256": "36d3820fc3a858f7fc39f35237475fe2a4897a6a38ceee19efbadf9426c6dcd4",
|
||||
"rawReceiptUnchanged": true
|
||||
}
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Bounded, attribution-only native Apple keychain lifecycle, without PFX/SDK/CLR."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
STAGES = ['before', 'first', 'repeated', 'idle']
|
||||
|
||||
|
||||
def save(path, value):
|
||||
path.write_text(json.dumps(value, indent=2) + '\n')
|
||||
|
||||
|
||||
def complete_rows(path):
|
||||
return [json.loads(line) for line in path.read_text().split('\n')[:-1]]
|
||||
|
||||
|
||||
def snapshot(pid, task, output, stage):
|
||||
heap = subprocess.run(['/usr/bin/heap', '--noContent', '-s', str(pid)], text=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, timeout=20, check=True)
|
||||
(output / ('heap-' + stage + '.txt')).write_text(heap.stdout)
|
||||
database = re.search(r'^\s*(\d+)\s+(\d+)\s+[\d.]+\s+Security::AppleDatabase\s', heap.stdout, re.MULTILINE)
|
||||
manager = re.search(r'^\s*(\d+)\s+(\d+)\s+[\d.]+\s+Security::AppleDatabaseManager\s', heap.stdout, re.MULTILINE)
|
||||
if database is None and manager is None:
|
||||
raise RuntimeError('Native inventory could not classify the database or its manager; do not silently infer zero')
|
||||
descriptors = subprocess.run(['/usr/sbin/lsof', '-a', '-p', str(pid), '-Fnf'], text=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=5, check=True)
|
||||
(output / ('lsof-' + stage + '.txt')).write_text(descriptors.stdout)
|
||||
total = temp = keychain = 0
|
||||
in_descriptor = False
|
||||
for line in descriptors.stdout.splitlines():
|
||||
if line.startswith('f'):
|
||||
in_descriptor = len(line) > 1 and line[1].isdigit()
|
||||
total += int(in_descriptor)
|
||||
elif in_descriptor and line.startswith('n/'):
|
||||
path = Path(line[1:].removesuffix(' (deleted)')).resolve()
|
||||
owned = path == task / 'tmp' or task / 'tmp' in path.parents
|
||||
temp += int(owned)
|
||||
keychain += int(owned and '.keychain' in path.name)
|
||||
return {'AppleDatabaseCount': int(database[1]) if database else 0,
|
||||
'AppleDatabaseShallowBytes': int(database[2]) if database else 0,
|
||||
'AppleDatabaseClassAbsent': database is None,
|
||||
'databaseManagerClassPresent': manager is not None, 'fdCount': total,
|
||||
'ownedTemporaryFdCount': temp, 'ownedKeychainFdCount': keychain,
|
||||
'ownedKeychainFileCount': sum(p.is_file() and '.keychain' in p.name for p in (task / 'tmp').rglob('*'))}
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--output', required=True, type=Path, help='Fresh private output directory')
|
||||
options = parser.parse_args()
|
||||
if sys.platform != 'darwin':
|
||||
parser.error('Native control requires macOS')
|
||||
output = options.output.resolve()
|
||||
output.mkdir(parents=True, exist_ok=False)
|
||||
os.chmod(output, 0o700)
|
||||
task = output / 'task'
|
||||
binary = output / 'PureAppleControl'
|
||||
command = ['clang', '-std=c11', '-O0', '-g', '-Wall', '-Wextra', str(HERE / 'PureAppleControl.c'),
|
||||
'-framework', 'Security', '-framework', 'CoreFoundation', '-o', str(binary)]
|
||||
source_hash = hashlib.sha256((HERE / 'PureAppleControl.c').read_bytes()).hexdigest()
|
||||
provenance = {'sourceSha256': source_hash, 'runnerSourceSha256': hashlib.sha256((HERE / 'pure_apple.py').read_bytes()).hexdigest(), 'compileCommand': command,
|
||||
'compiler': subprocess.check_output(['clang', '--version'], text=True),
|
||||
'os': subprocess.check_output(['sw_vers'], text=True), 'architecture': os.uname().machine,
|
||||
'repetitions': 200, 'idleSeconds': 5, 'stages': STAGES, 'fullSoakGate': False,
|
||||
'readOnlyKeychainQueries': ['SecKeychainCopyDefault', 'SecKeychainCopySearchList', 'SecKeychainGetPath'],
|
||||
'doesNotCallAnyDefaultOrSearchListSetter': True}
|
||||
save(output / 'provenance.json', provenance)
|
||||
with (output / 'build.log').open('w') as log:
|
||||
subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, timeout=60, check=True)
|
||||
provenance['binarySha256'] = hashlib.sha256(binary.read_bytes()).hexdigest()
|
||||
provenance['linkedLibraries'] = subprocess.check_output(['otool', '-L', str(binary)], text=True)
|
||||
if 'libcoreclr' in provenance['linkedLibraries'] or 'Opc.Ua' in provenance['linkedLibraries']:
|
||||
raise RuntimeError('Pure Apple control must not load SDK or CLR')
|
||||
save(output / 'provenance.json', provenance)
|
||||
task.mkdir(mode=0o700)
|
||||
(task / 'tmp').mkdir(mode=0o700)
|
||||
started = time.monotonic()
|
||||
with (output / 'samples.jsonl').open('w') as log:
|
||||
process = subprocess.Popen([str(binary), str(task)], stdout=log, stderr=subprocess.STDOUT,
|
||||
env=dict(os.environ, TMPDIR=str(task / 'tmp')))
|
||||
try:
|
||||
deadline = time.monotonic() + 180
|
||||
samples = []
|
||||
for stage in STAGES:
|
||||
while True:
|
||||
rows = complete_rows(output / 'samples.jsonl')
|
||||
if any(row['kind'] == 'failed' for row in rows):
|
||||
raise RuntimeError('Native control failed; preserve raw status rows')
|
||||
checkpoints = [row for row in rows if row.get('stage') == stage and row['kind'] == 'checkpoint']
|
||||
if checkpoints:
|
||||
samples.append({**checkpoints[0], **snapshot(process.pid, task, output, stage)})
|
||||
(task / ('continue-' + stage)).touch()
|
||||
break
|
||||
if process.poll() is not None or time.monotonic() >= deadline:
|
||||
raise RuntimeError('Native checkpoint exceeded bound: ' + stage)
|
||||
time.sleep(.05)
|
||||
status = process.wait(timeout=15)
|
||||
rows = complete_rows(output / 'samples.jsonl')
|
||||
operations = [r for r in rows if r['kind'] == 'operation']
|
||||
fingerprints = [r for r in rows if r['kind'] == 'fingerprint']
|
||||
complete = [r for r in rows if r['kind'] == 'complete']
|
||||
if status or len(operations) != 200 or len(fingerprints) != 2 or len(complete) != 1:
|
||||
raise RuntimeError('Incomplete native execution count')
|
||||
if any(r['createStatus'] or r['deleteStatus'] or not r['privatePathVerified'] or not r['releasedExactlyOnce'] for r in operations):
|
||||
raise RuntimeError('Native lifecycle status/ownership failed')
|
||||
if any(samples[-1][k] for k in ['ownedKeychainFdCount', 'ownedKeychainFileCount']):
|
||||
raise RuntimeError('Private native keychain files/descriptors retained')
|
||||
result = {'status': 'passed', 'exitCode': status, 'wallSecondsIncludingProbes': time.monotonic() - started,
|
||||
'samples': samples, 'fingerprints': fingerprints, 'complete': complete[0], 'fullSoakGate': False,
|
||||
'nativeInventoryIsNotOpenHandlesOrExclusiveRss': True, 'nativeDeleteOsStatusesAllZero': True}
|
||||
save(output / 'result.json', result)
|
||||
finally:
|
||||
if process.poll() is None:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill(); process.wait(timeout=5)
|
||||
save(output / 'fixture-before-harness-cleanup.json', {'remainingOwnedKeychainFiles': sum(p.is_file() and '.keychain' in p.name for p in (task / 'tmp').rglob('*'))})
|
||||
shutil.rmtree(task)
|
||||
save(output / 'fixture-cleanup.json', {'ownedFixtureRootRemoved': not task.exists()})
|
||||
print(output)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,168 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Bounded attribution-only macOS SDK private-key reload/registry controls."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
STAGES = ['ready', 'first', 'repeated', 'disposed', 'idle']
|
||||
|
||||
|
||||
def save(path, value):
|
||||
path.write_text(json.dumps(value, indent=2) + '\n')
|
||||
|
||||
|
||||
def snapshots(pid, root, stage):
|
||||
# These raw, no-content inventory files remain private/local and are not release artifacts.
|
||||
heap = subprocess.run(['/usr/bin/heap', '--noContent', '-s', str(pid)], text=True, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, timeout=20, check=True)
|
||||
(root / ('heap-' + stage + '.txt')).write_text(heap.stdout)
|
||||
match = re.search(r'^\s*(\d+)\s+(\d+)\s+[\d.]+\s+Security::AppleDatabase\s', heap.stdout, re.MULTILINE)
|
||||
if not match:
|
||||
raise RuntimeError('AppleDatabase inventory class missing; diagnostic cannot silently report zero')
|
||||
descriptors = subprocess.run(['/usr/sbin/lsof', '-a', '-p', str(pid), '-Fnf'], text=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=5, check=True)
|
||||
(root / ('lsof-' + stage + '.txt')).write_text(descriptors.stdout)
|
||||
total = pki = temporary = keychain = 0
|
||||
in_descriptor = False
|
||||
pki_root = (root / 'pki').resolve()
|
||||
tmp_root = (root / 'tmp').resolve()
|
||||
for line in descriptors.stdout.splitlines():
|
||||
if line.startswith('f'):
|
||||
in_descriptor = len(line) > 1 and line[1].isdigit()
|
||||
total += int(in_descriptor)
|
||||
elif in_descriptor and line.startswith('n/'):
|
||||
target = Path(line[1:].removesuffix(' (deleted)')).resolve()
|
||||
pki += int(target == pki_root or pki_root in target.parents)
|
||||
in_temp = target == tmp_root or tmp_root in target.parents
|
||||
temporary += int(in_temp)
|
||||
keychain += int(in_temp and '.keychain' in target.name)
|
||||
if pki:
|
||||
raise RuntimeError('Quiescent task-owned PKI descriptors are open')
|
||||
if stage in ['disposed', 'idle'] and keychain:
|
||||
raise RuntimeError('Owned temporary keychain descriptors remain after application disposal')
|
||||
return {'stage': stage, 'AppleDatabaseCount': int(match[1]), 'AppleDatabaseShallowBytes': int(match[2]),
|
||||
'fdCount': total, 'pkiFdCount': pki, 'temporaryDirectoryFdCount': temporary,
|
||||
'temporaryKeychainFdCount': keychain,
|
||||
'temporaryKeychainFileCount': sum(p.is_file() and '.keychain' in p.name for p in (root / 'tmp').rglob('*'))}
|
||||
|
||||
|
||||
def arm(app, root, mode):
|
||||
(root / 'tmp').mkdir()
|
||||
(root / 'data').mkdir()
|
||||
env = dict(os.environ, OPCUA_CERTIFICATE_LEAK_TRACKING='1', TMPDIR=str(root / 'tmp'), XDG_DATA_HOME=str(root / 'data'))
|
||||
with (root / 'samples.jsonl').open('w') as log:
|
||||
process = subprocess.Popen(['dotnet', str(app), mode, str(root)], stdout=log, stderr=subprocess.STDOUT, env=env)
|
||||
try:
|
||||
deadline = time.monotonic() + 180
|
||||
values = []
|
||||
for stage in STAGES:
|
||||
while True:
|
||||
text = (root / 'samples.jsonl').read_text()
|
||||
rows = [json.loads(line) for line in text.split('\n')[:-1]]
|
||||
if any(row.get('kind') == 'failed' for row in rows):
|
||||
raise RuntimeError('Control failed; see samples.jsonl')
|
||||
matching = [row for row in rows if row.get('stage') == stage]
|
||||
if matching:
|
||||
values.append({**matching[0], **snapshots(process.pid, root, stage)})
|
||||
(root / ('continue-' + stage)).touch()
|
||||
break
|
||||
if process.poll() is not None or time.monotonic() >= deadline:
|
||||
raise RuntimeError('Control checkpoint did not complete within bound: ' + stage)
|
||||
time.sleep(.05)
|
||||
status = process.wait(timeout=15)
|
||||
rows = [json.loads(line) for line in (root / 'samples.jsonl').read_text().splitlines()]
|
||||
complete = [row for row in rows if row.get('kind') == 'complete']
|
||||
if status or len(complete) != 1 or complete[0]['operations'] != 200:
|
||||
raise RuntimeError('Control failed or acquisition count changed')
|
||||
result = {'exitCode': status, 'complete': complete[0], 'samples': values,
|
||||
'nativeCountIsNotOpenHandleOrExclusiveRssAttribution': True,
|
||||
'registryArmIsNotApprovedProductionMitigation': True}
|
||||
save(root / 'result.json', result)
|
||||
return result
|
||||
finally:
|
||||
if process.poll() is None:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=10)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait(timeout=5)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--references', required=True, type=Path, help='Actual immutable published SDK2 DLL directory')
|
||||
parser.add_argument('--output', required=True, type=Path, help='Fresh private output; contains PKI and native snapshots')
|
||||
options = parser.parse_args()
|
||||
if sys.platform != 'darwin':
|
||||
parser.error('This native attribution control requires macOS')
|
||||
out = options.output.resolve()
|
||||
out.mkdir(parents=True, exist_ok=False)
|
||||
os.chmod(out, 0o700)
|
||||
sdk = sorted(options.references.resolve().glob('Opc.Ua*.dll'))
|
||||
if not sdk:
|
||||
raise RuntimeError('Missing actual SDK assemblies')
|
||||
project = ET.Element('Project', Sdk='Microsoft.NET.Sdk')
|
||||
props = ET.SubElement(project, 'PropertyGroup')
|
||||
for k, v in {'OutputType': 'Exe', 'TargetFramework': 'net10.0', 'ImplicitUsings': 'enable', 'Nullable': 'enable',
|
||||
'EnableDefaultCompileItems': 'false', 'TreatWarningsAsErrors': 'true'}.items():
|
||||
ET.SubElement(props, k).text = v
|
||||
items = ET.SubElement(project, 'ItemGroup')
|
||||
ET.SubElement(items, 'FrameworkReference', Include='Microsoft.AspNetCore.App')
|
||||
ET.SubElement(items, 'Compile', Include=str(HERE / 'ReloadControl.cs'))
|
||||
for dll in sdk:
|
||||
ref = ET.SubElement(items, 'Reference', Include=dll.stem)
|
||||
ET.SubElement(ref, 'HintPath').text = str(dll)
|
||||
ET.indent(project)
|
||||
ET.ElementTree(project).write(out / 'Control.csproj', encoding='unicode')
|
||||
sha = lambda p: hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
provenance = {'controlSourceSha256': sha(HERE / 'ReloadControl.cs'), 'runnerSourceSha256': sha(HERE / 'run.py'),
|
||||
'repetitionsPerArm': 200, 'stages': STAGES, 'idleSeconds': 5, 'fullSoakGate': False,
|
||||
'leakTracking': True, 'trackingOverhead': 'Both A/B processes capture allocation stacks; additional allocation and GC overhead is included in observed memory.',
|
||||
'nativeReferences': {p.name: sha(p) for p in sdk}, 'hostDotnet': subprocess.check_output(['dotnet', '--info'], text=True),
|
||||
'os': subprocess.check_output(['sw_vers'], text=True), 'architecture': os.uname().machine}
|
||||
save(out / 'provenance.json', provenance)
|
||||
with (out / 'build.log').open('w') as log:
|
||||
subprocess.run(['dotnet', 'build', str(out / 'Control.csproj'), '-c', 'Release', '-m:1', '--nologo'],
|
||||
stdout=log, stderr=subprocess.STDOUT, timeout=120, check=True)
|
||||
app = out / 'bin/Release/net10.0/Control.dll'
|
||||
seed = out / 'seed'
|
||||
seed.mkdir()
|
||||
(seed / 'tmp').mkdir()
|
||||
(seed / 'data').mkdir()
|
||||
results = {}
|
||||
try:
|
||||
with (seed / 'seed.jsonl').open('w') as log:
|
||||
subprocess.run(['dotnet', str(app), 'seed', str(seed)], stdout=log, stderr=subprocess.STDOUT, timeout=60, check=True,
|
||||
env=dict(os.environ, TMPDIR=str(seed / 'tmp'), XDG_DATA_HOME=str(seed / 'data')))
|
||||
seed_rows = [json.loads(x) for x in (seed / 'seed.jsonl').read_text().splitlines()]
|
||||
assert len(seed_rows) == 1 and seed_rows[0]['kind'] == 'seed'
|
||||
provenance['cryptographyRuntime'] = seed_rows[0]['cryptographyRuntime']
|
||||
save(out / 'provenance.json', provenance)
|
||||
for mode in ['store', 'registry']:
|
||||
root = out / mode
|
||||
root.mkdir()
|
||||
shutil.copytree(seed / 'pki', root / 'pki')
|
||||
results[mode] = arm(app, root, mode)
|
||||
assert results['store']['complete']['sameLeafSha256'] == results['registry']['complete']['sameLeafSha256'] == seed_rows[0]['leafSha256']
|
||||
save(out / 'result.json', {'status': 'passed', 'seed': seed_rows[0], 'arms': results, 'fullSoakGate': False})
|
||||
finally:
|
||||
for root in [seed, out / 'store', out / 'registry']:
|
||||
for name in ['pki', 'tmp', 'data']:
|
||||
if (root / name).exists():
|
||||
shutil.rmtree(root / name)
|
||||
save(out / 'fixture-cleanup.json', {'allOwnedFixtureDirectoriesRemoved': all(not (p / name).exists() for p in [seed, out / 'store', out / 'registry'] for name in ['pki', 'tmp', 'data'])})
|
||||
print(out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -52,12 +52,10 @@ verified diagnostic), RID `linux-arm64`, self-contained runtime 10.0.14, explici
|
||||
node, and an external task-owned artifacts directory. All runtime packs were
|
||||
already cached. No production or test source is patched during publish. The
|
||||
launcher requires an empty production/package source diff against the reviewed
|
||||
`67bc6123` production tree and
|
||||
`cd60e469` production tree and
|
||||
records the actual published revision separately from the launcher revision.
|
||||
The reference was advanced from `7b353d7b` after review of comment-only edits,
|
||||
then to `67bc6123` for the independently reviewed/tested HG1.0 adapter/package
|
||||
change. Canonical SDK server code is unchanged by that consumer update. Historical
|
||||
receipts retain their actual source/reference hashes.
|
||||
The reference was advanced from `7b353d7b` after source review of comment-only
|
||||
production edits; historical receipts retain their actual source/reference hashes.
|
||||
That is source equivalence, not a claim that separately built Linux and macOS
|
||||
assemblies have identical hashes. The full publish file hashes, exact test source
|
||||
hash, runtimeconfig and SDK dependency versions are retained.
|
||||
|
||||
@@ -17,7 +17,7 @@ ROOT = HERE.parents[2]
|
||||
PROJECT = ROOT / 'tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests.csproj'
|
||||
APPNAME = 'ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests'
|
||||
TARGET = 'Repeated_lifecycles_return_resources_to_a_steady_baseline'
|
||||
BASE = '67bc61236a7798e87deb9ae45e54bd29cf3d8ae9'
|
||||
BASE = 'cd60e469a100412ee08f598accad07a6959778ba'
|
||||
|
||||
|
||||
def write(path, value):
|
||||
@@ -97,7 +97,7 @@ def main():
|
||||
revision = subprocess.check_output(['git', '-C', str(ROOT), 'rev-parse', 'HEAD'], text=True).strip()
|
||||
production_diff = subprocess.check_output(['git', '-C', str(ROOT), 'diff', BASE, 'HEAD', '--', 'src', 'Directory.Packages.props', 'Directory.Build.props'], text=True)
|
||||
if production_diff:
|
||||
raise RuntimeError('Production/package source differs from reviewed ' + BASE[:8] + ' source; review required')
|
||||
raise RuntimeError('Production/package source differs from reviewed cd60e469 source; review required')
|
||||
image = json.loads(subprocess.check_output(['docker', 'image', 'inspect', args.image, '--format', '{{json .}}'], text=True))
|
||||
if image['Architecture'] != 'arm64' or image['Os'] != 'linux':
|
||||
raise RuntimeError('Expected cached official Linux ARM64 image')
|
||||
|
||||
@@ -175,9 +175,6 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
|
||||
private StandardServer? _server;
|
||||
private readonly ITelemetryContext _telemetry = DefaultTelemetry.Create(_ => { });
|
||||
private readonly List<IUserTokenAuthenticator> _identityAuthenticators = [];
|
||||
private readonly object _lifetimeLock = new();
|
||||
private readonly TaskCompletionSource _disposeCompletion = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
private int _disposeStarted;
|
||||
|
||||
/// <summary>Initializes a new instance of the OPC UA application host.</summary>
|
||||
/// <param name="options">The host configuration options.</param>
|
||||
@@ -205,21 +202,18 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public async Task StartAsync(StandardServer server, CancellationToken cancellationToken)
|
||||
{
|
||||
OtOpcUaSdkServer sdkServer;
|
||||
lock (_lifetimeLock)
|
||||
if (server is not OtOpcUaSdkServer sdkServer)
|
||||
throw new ArgumentException("The server must support application authentication before its listeners open.", nameof(server));
|
||||
_server = server;
|
||||
// ApplicationInstance receives the host's ITelemetryContext. DefaultTelemetry.Create wires
|
||||
// the SDK's internal logging; an empty builder keeps
|
||||
// the SDK's trace off our ILogger (the host keeps its own _logger) — sufficient for the bootstrap.
|
||||
_application = new ApplicationInstance(_telemetry)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(Volatile.Read(ref _disposeStarted) != 0, this);
|
||||
sdkServer = server as OtOpcUaSdkServer
|
||||
?? throw new ArgumentException("The server must support application authentication before its listeners open.", nameof(server));
|
||||
_server = server;
|
||||
// The empty telemetry builder keeps SDK tracing separate from the host's ILogger.
|
||||
_application = new ApplicationInstance(_telemetry)
|
||||
{
|
||||
ApplicationName = _options.ApplicationName,
|
||||
ApplicationType = ApplicationType.Server,
|
||||
ConfigSectionName = "OtOpcUa",
|
||||
};
|
||||
}
|
||||
ApplicationName = _options.ApplicationName,
|
||||
ApplicationType = ApplicationType.Server,
|
||||
ConfigSectionName = "OtOpcUa",
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
@@ -646,63 +640,16 @@ public sealed class OpcUaApplicationHost : IAsyncDisposable
|
||||
|
||||
/// <summary>Disposes the application host and cleans up resources.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public ValueTask DisposeAsync()
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _disposeStarted, 1, 0) == 0)
|
||||
_ = CompleteDisposalAsync();
|
||||
return new ValueTask(_disposeCompletion.Task);
|
||||
}
|
||||
|
||||
private async Task CompleteDisposalAsync()
|
||||
{
|
||||
Exception? failure = null;
|
||||
try
|
||||
// Authenticators remain installed until the SDK closes every listener and disposes its registry.
|
||||
if (_application is { } application)
|
||||
{
|
||||
ApplicationInstance? application;
|
||||
StandardServer? server;
|
||||
bool adopted;
|
||||
lock (_lifetimeLock)
|
||||
{
|
||||
application = _application;
|
||||
server = _server;
|
||||
// SDK2 adopts the server only when ApplicationInstance.StartAsync is reached.
|
||||
adopted = server is not null && ReferenceEquals(application?.Server, server);
|
||||
_application = null;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (application is not null)
|
||||
{
|
||||
try { await application.DisposeAsync().ConfigureAwait(false); }
|
||||
catch (Exception ex) { _logger.LogWarning(ex, "OpcUaApplicationHost: disposal threw"); }
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Failed configuration/certificate work may precede the application's ownership handoff.
|
||||
// An adopted server remains solely owned by ApplicationInstance.DisposeAsync.
|
||||
if (!adopted)
|
||||
{
|
||||
try { if (server is not null) await server.DisposeAsync().ConfigureAwait(false); }
|
||||
catch (Exception ex) { _logger.LogWarning(ex, "OpcUaApplicationHost: unadopted server disposal threw"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception error) { failure = error; }
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
// Only the cleanup owner clears adapters after every listener and registry has closed.
|
||||
_identityAuthenticators.Clear();
|
||||
_server = null;
|
||||
}
|
||||
catch (Exception error) { failure = failure is null ? error : new AggregateException(failure, error); }
|
||||
finally
|
||||
{
|
||||
if (failure is null) _disposeCompletion.TrySetResult();
|
||||
else _disposeCompletion.TrySetException(failure);
|
||||
}
|
||||
_application = null;
|
||||
try { await application.DisposeAsync().ConfigureAwait(false); }
|
||||
catch (Exception ex) { _logger.LogWarning(ex, "OpcUaApplicationHost: disposal threw"); }
|
||||
}
|
||||
_identityAuthenticators.Clear();
|
||||
_server = null;
|
||||
}
|
||||
}
|
||||
|
||||
-3
@@ -122,15 +122,12 @@ public sealed class EventHistoryPagingOverTheWireTests
|
||||
/// <summary>(time, id) order, [start, end), cap + truncation flag — the SQL backends' contract.</summary>
|
||||
internal sealed class SqlLikeEventSource(List<HistoricalEvent> events) : IHistorianDataSource
|
||||
{
|
||||
private int _reads;
|
||||
internal int ReadCount => Volatile.Read(ref _reads);
|
||||
private readonly List<HistoricalEvent> _all =
|
||||
events.OrderBy(e => e.EventTimeUtc).ThenBy(e => e.EventId, StringComparer.Ordinal).ToList();
|
||||
|
||||
public async Task<HistoricalEventsResult> ReadEventsAsync(
|
||||
string? sourceName, DateTime startUtc, DateTime endUtc, int maxEvents, CancellationToken ct)
|
||||
{
|
||||
Interlocked.Increment(ref _reads);
|
||||
await Task.Delay(1, ct).ConfigureAwait(false); // complete on a pool thread, like a real backend
|
||||
var window = _all.Where(e => e.EventTimeUtc >= startUtc && e.EventTimeUtc < endUtc).ToList();
|
||||
var cap = maxEvents <= 0 ? 1000 : maxEvents;
|
||||
|
||||
-99
@@ -1,99 +0,0 @@
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Configuration;
|
||||
using Opc.Ua.Server;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ClientSession = Opc.Ua.Client.ISession;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests;
|
||||
|
||||
public sealed partial class Sdk2LifecycleSoakTests
|
||||
{
|
||||
/// <summary>Concurrent host disposal awaits real encrypted-session shutdown before clearing ownership.</summary>
|
||||
[Fact]
|
||||
public async Task Concurrent_host_disposal_waits_for_the_actual_encrypted_session_to_close()
|
||||
{
|
||||
var ct = TestContext.Current.CancellationToken;
|
||||
var clientRoot = Path.Combine(Path.GetTempPath(), $"otua-dispose-client-{Guid.NewGuid():N}");
|
||||
ApplicationInstance? application = null;
|
||||
ServerEventRig? rig = null;
|
||||
ClientSession? client = null;
|
||||
ISessionManager? sessionManager = null;
|
||||
SessionEventHandler? closing = null;
|
||||
using var release = new ManualResetEventSlim(false);
|
||||
var entered = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var calls = new List<Task>();
|
||||
var timedOut = 0;
|
||||
var callbackCount = 0;
|
||||
try
|
||||
{
|
||||
var telemetry = DefaultTelemetry.Create(_ => { });
|
||||
var security = TestClientSecurity.Build(clientRoot);
|
||||
security.ApplicationCertificate!.SubjectName = "CN=SDK2LifecycleSoak";
|
||||
var config = new ApplicationConfiguration(telemetry)
|
||||
{
|
||||
ApplicationName = "SDK2LifecycleSoak", ApplicationUri = $"urn:SDK2LifecycleSoak:{Guid.NewGuid():N}",
|
||||
ApplicationType = ApplicationType.Client, SecurityConfiguration = security,
|
||||
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 15_000 },
|
||||
TransportQuotas = new TransportQuotas { OperationTimeout = 5000 },
|
||||
};
|
||||
application = new ApplicationInstance(telemetry) { ApplicationConfiguration = config };
|
||||
await config.ValidateAsync(ApplicationType.Client, ct);
|
||||
await application.CheckApplicationInstanceCertificatesAsync(true, null, ct);
|
||||
rig = await ServerEventRig.StartAsync("SDK2ConcurrentDisposal", encrypted: true, ct);
|
||||
Configure(rig);
|
||||
client = await ConnectAsync(rig, config, null, ct);
|
||||
sessionManager = rig.Server.CurrentInstance.SessionManager;
|
||||
sessionManager.GetSessions().Count.ShouldBe(1);
|
||||
var sessionId = client.SessionId;
|
||||
closing = (session, reason) =>
|
||||
{
|
||||
if (session.Id != sessionId || reason != SessionEventReason.Closing) return;
|
||||
Interlocked.Increment(ref callbackCount);
|
||||
entered.TrySetResult();
|
||||
// SDK swallows event exceptions; keep an explicit failure flag for this bounded barrier.
|
||||
if (!release.Wait(TimeSpan.FromSeconds(15))) Interlocked.Exchange(ref timedOut, 1);
|
||||
};
|
||||
sessionManager.SessionClosing += closing;
|
||||
var host = RequiredField<OpcUaApplicationHost>(rig, "_host");
|
||||
var manager = rig.Server.CertificateManager!;
|
||||
calls.Add(Task.Run(async () => await host.DisposeAsync(), ct));
|
||||
await entered.Task.WaitAsync(TimeSpan.FromSeconds(10), ct);
|
||||
for (var i = 0; i < 3; i++) calls.Add(host.DisposeAsync().AsTask());
|
||||
calls.ShouldAllBe(call => !call.IsCompleted, "every caller must await the actual shutdown owner");
|
||||
host.Server.ShouldBeSameAs(rig.Server);
|
||||
RequiredField<bool>(manager, "m_disposed").ShouldBeFalse();
|
||||
release.Set();
|
||||
await Task.WhenAll(calls).WaitAsync(TimeSpan.FromSeconds(20), ct);
|
||||
Volatile.Read(ref timedOut).ShouldBe(0);
|
||||
Volatile.Read(ref callbackCount).ShouldBe(1);
|
||||
host.Server.ShouldBeNull();
|
||||
host.ApplicationInstance.ShouldBeNull();
|
||||
RequiredField<bool>(manager, "m_disposed").ShouldBeTrue();
|
||||
CertificateCores(manager).Sum(CachedStores).ShouldBe(0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Removing a handler takes the SDK's event lock: release before awaiting or unsubscribing.
|
||||
release.Set();
|
||||
try { await Task.WhenAll(calls).WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None); }
|
||||
finally
|
||||
{
|
||||
try { if (sessionManager is not null && closing is not null) sessionManager.SessionClosing -= closing; }
|
||||
finally
|
||||
{
|
||||
try { client?.Dispose(); }
|
||||
finally
|
||||
{
|
||||
try { if (rig is not null) await rig.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None); }
|
||||
finally
|
||||
{
|
||||
try { if (application is not null) await application.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None); }
|
||||
finally { if (Directory.Exists(clientRoot)) Directory.Delete(clientRoot, true); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-248
@@ -1,248 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Client;
|
||||
using Opc.Ua.Configuration;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests;
|
||||
|
||||
public sealed partial class Sdk2LifecycleSoakTests
|
||||
{
|
||||
public static bool CloseControlEnabled =>
|
||||
Environment.GetEnvironmentVariable("OTOPCUA_SDK2_CLOSE_CONTROL") == "1";
|
||||
|
||||
[Fact(SkipUnless = nameof(CloseControlEnabled), Skip = "Opt in to the bounded SDK2 close/weak-root control.")]
|
||||
public async Task Closed_tokens_are_rejected_and_ownership_is_observed_without_harness_roots()
|
||||
{
|
||||
using var deadline = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken);
|
||||
deadline.CancelAfter(TimeSpan.FromSeconds(120));
|
||||
var ct = deadline.Token;
|
||||
// Positive and negative controls for the observer itself, independent of SDK objects.
|
||||
var alive = new object();
|
||||
var aliveReference = new WeakReference(alive);
|
||||
var collectible = CollectibleReference();
|
||||
var observer = await ObserveWeakAsync([new("retained-control", aliveReference), new("collectible-control", collectible)], ct);
|
||||
observer.Last().Alive.ShouldBe([true, false]);
|
||||
GC.KeepAlive(alive);
|
||||
WriteCloseControl("observer-controls", observer);
|
||||
|
||||
// The helper returns no rig, application, config, Session, point or store objects.
|
||||
var stoppedTargets = await Task.Run(() => RunCloseFixture(ct), ct).WaitAsync(TimeSpan.FromSeconds(120), ct);
|
||||
var stopped = await ObserveWeakAsync(stoppedTargets, ct);
|
||||
WriteCloseControl("after-normal-host-stop", stopped);
|
||||
stopped.Last().Alive.ShouldAllBe(value => !value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakReference CollectibleReference() => new(new object());
|
||||
|
||||
private sealed record WeakTarget(string Kind, WeakReference Reference);
|
||||
private sealed record WeakObservation(int Collection, string[] Kinds, bool[] Alive);
|
||||
|
||||
private static async Task<WeakObservation[]> ObserveWeakAsync(WeakTarget[] targets, CancellationToken ct)
|
||||
{
|
||||
var observations = new List<WeakObservation>();
|
||||
// Fixed count/delay; no extension or retrieving/resurrecting targets during collection.
|
||||
var delays = new[] { 50, 100, 250, 500, 1000 };
|
||||
for (var i = 0; i < delays.Length; i++)
|
||||
{
|
||||
ct.ThrowIfCancellationRequested();
|
||||
await Task.Run(() =>
|
||||
{
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true, compacting: true);
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, blocking: true, compacting: true);
|
||||
}, ct).WaitAsync(TimeSpan.FromSeconds(5), ct);
|
||||
await Task.Delay(delays[i], ct);
|
||||
observations.Add(new(i + 1, targets.Select(t => t.Kind).ToArray(), targets.Select(t => t.Reference.IsAlive).ToArray()));
|
||||
}
|
||||
return observations.ToArray();
|
||||
}
|
||||
|
||||
private static void WriteCloseControl(string phase, object observation) =>
|
||||
TestContext.Current.TestOutputHelper!.WriteLine(JsonSerializer.Serialize(new { phase, observation, acceptance = false }));
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakTarget[] RunCloseFixture(CancellationToken ct) => ExerciseCloseOwnershipAsync(ct).GetAwaiter().GetResult();
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static WeakTarget[] RunClosedSession(ServerEventRig rig, ApplicationConfiguration config, CancellationToken ct) =>
|
||||
CloseAndDenyOldTokensAsync(rig, config, ct).GetAwaiter().GetResult();
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static async Task<WeakTarget[]> ExerciseCloseOwnershipAsync(CancellationToken ct)
|
||||
{
|
||||
var clientRoot = Path.Combine(Path.GetTempPath(), $"otua-close-client-{Guid.NewGuid():N}");
|
||||
var telemetry = DefaultTelemetry.Create(_ => { });
|
||||
var security = TestClientSecurity.Build(clientRoot);
|
||||
security.ApplicationCertificate!.SubjectName = "CN=SDK2LifecycleSoak";
|
||||
var config = new ApplicationConfiguration(telemetry)
|
||||
{
|
||||
ApplicationName = "SDK2LifecycleSoak", ApplicationUri = $"urn:SDK2LifecycleSoak:{Guid.NewGuid():N}",
|
||||
ApplicationType = ApplicationType.Client, SecurityConfiguration = security,
|
||||
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 15_000 },
|
||||
TransportQuotas = new TransportQuotas { OperationTimeout = 5000 },
|
||||
};
|
||||
ApplicationInstance? application = new(telemetry) { ApplicationConfiguration = config };
|
||||
ServerEventRig? rig = null;
|
||||
Exception? originalFailure = null;
|
||||
try
|
||||
{
|
||||
await config.ValidateAsync(ApplicationType.Client, ct);
|
||||
await application.CheckApplicationInstanceCertificatesAsync(true, null, ct);
|
||||
rig = await ServerEventRig.StartAsync("SDK2CloseOwnership", encrypted: true, ct);
|
||||
Configure(rig);
|
||||
var closedTargets = RunClosedSession(rig, config, ct);
|
||||
var closed = await ObserveWeakAsync(closedTargets, ct);
|
||||
WriteCloseControl("closed-objects-same-host-live", closed);
|
||||
closed.Last().Alive.ShouldAllBe(value => !value);
|
||||
GC.KeepAlive(rig);
|
||||
|
||||
var clientManager = config.CertificateManager;
|
||||
var serverManager = rig.Server.CertificateManager!;
|
||||
var serverApplication = RequiredField<OpcUaApplicationHost>(rig, "_host").ApplicationInstance!;
|
||||
var cores = CertificateCores(clientManager).Concat(CertificateCores(serverManager)).ToArray();
|
||||
var stoppedTargets = new List<WeakTarget>
|
||||
{
|
||||
new("client-application", new(application)), new("client-config", new(config)),
|
||||
new("client-manager", new(clientManager)), new("server-manager", new(serverManager)),
|
||||
new("server-application", new(serverApplication)),
|
||||
new("server-rig", new(rig)), new("server", new(rig.Server)),
|
||||
new("node-manager", new(rig.Nm)), new("event-source", new(rig.Nm.HistorianDataSource!)),
|
||||
};
|
||||
foreach (var core in cores)
|
||||
{
|
||||
stoppedTargets.Add(new("certificate-validation-core", new(core)));
|
||||
foreach (var store in RequiredField<IDictionary>(core, "m_stores").Values)
|
||||
if (store is not null) stoppedTargets.Add(new("cached-store", new(store)));
|
||||
}
|
||||
await rig.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), ct);
|
||||
await application.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), ct);
|
||||
application = null;
|
||||
RequiredField<bool>(clientManager, "m_disposed").ShouldBeTrue();
|
||||
RequiredField<bool>(serverManager, "m_disposed").ShouldBeTrue();
|
||||
cores.Sum(CachedStores).ShouldBe(0);
|
||||
(await DescriptorCountsAsync(ct, clientRoot, RequiredField<string>(rig, "_pkiRoot"))).Pki.ShouldBe(0);
|
||||
rig = null;
|
||||
WriteCloseControl("sdk2-disposal-proofs", new { managersDisposed = 2, cachedStores = 0, pkiDescriptors = 0 });
|
||||
return stoppedTargets.ToArray();
|
||||
}
|
||||
catch (Exception error)
|
||||
{
|
||||
originalFailure = error;
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
var cleanupFailures = new List<Exception>();
|
||||
try
|
||||
{
|
||||
try { if (rig is not null) await rig.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20)); }
|
||||
catch (Exception error) { cleanupFailures.Add(error); }
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
try { if (application is not null) await application.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20)); }
|
||||
catch (Exception error) { cleanupFailures.Add(error); }
|
||||
}
|
||||
finally
|
||||
{
|
||||
try { if (Directory.Exists(clientRoot)) Directory.Delete(clientRoot, true); }
|
||||
catch (Exception error) { cleanupFailures.Add(error); }
|
||||
}
|
||||
}
|
||||
if (cleanupFailures.Count > 0)
|
||||
{
|
||||
if (originalFailure is not null) cleanupFailures.Insert(0, originalFailure);
|
||||
throw new AggregateException("Close-control cleanup failed; original failure retained when present.", cleanupFailures);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static async Task<WeakTarget[]> CloseAndDenyOldTokensAsync(ServerEventRig rig,
|
||||
ApplicationConfiguration config, CancellationToken ct)
|
||||
{
|
||||
using var old = await ConnectAsync(rig, config, null, ct);
|
||||
var authenticationProperty = typeof(ClientBase).GetProperty("AuthenticationToken", BindingFlags.Instance | BindingFlags.NonPublic)
|
||||
?? throw new InvalidOperationException("Exact SDK2 authentication diagnostic is unavailable.");
|
||||
authenticationProperty.PropertyType.ShouldBe(typeof(NodeId));
|
||||
var oldAuthentication = authenticationProperty.GetValue(old).ShouldBeOfType<NodeId>();
|
||||
oldAuthentication.IsNull.ShouldBeFalse();
|
||||
var browse = await BrowseAsync(old, ct);
|
||||
ByteString history = default;
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
var point = (await PageAsync(old, default, false, ct)).ContinuationPoint;
|
||||
point.IsEmpty.ShouldBeFalse();
|
||||
if (i == 0) history = point;
|
||||
}
|
||||
browse.IsEmpty.ShouldBeFalse(); history.IsEmpty.ShouldBeFalse();
|
||||
var serverSession = rig.Server.CurrentInstance.SessionManager.GetSessions().Single();
|
||||
var points = serverSession.ContinuationPoints;
|
||||
ContinuationCounts(serverSession).ShouldBe((1, 6));
|
||||
var weak = new List<WeakTarget>
|
||||
{
|
||||
new("closed-client-session", new(old)), new("closed-server-session", new(serverSession)),
|
||||
new("closed-point-owner", new(points)),
|
||||
};
|
||||
using (RequiredField<System.Threading.Lock>(points, "m_lock").EnterScope())
|
||||
foreach (var field in new[] { "m_browse", "m_history" })
|
||||
foreach (var point in RequiredField<IEnumerable>(points, field))
|
||||
{
|
||||
weak.Add(new(field, new(point)));
|
||||
if (point is Opc.Ua.Server.ContinuationPoint browsePoint && browsePoint.Data is { } data)
|
||||
weak.Add(new("browse-data", new(data)));
|
||||
if (field == "m_history")
|
||||
{
|
||||
var value = point.GetType().GetField("Value")!.GetValue(point)!;
|
||||
weak.Add(new("history-value", new(value)));
|
||||
weak.Add(new("history-state", new(value.GetType().GetProperty("State")!.GetValue(value)!)));
|
||||
}
|
||||
}
|
||||
await old.CloseAsync(ct).WaitAsync(TimeSpan.FromSeconds(10), ct);
|
||||
rig.Server.CurrentInstance.SessionManager.GetSessions().ShouldBeEmpty();
|
||||
ContinuationCounts(serverSession).ShouldBe((0, 0));
|
||||
|
||||
using var fresh = await ConnectAsync(rig, config, null, ct);
|
||||
await OwnPointsRoundTripAsync(fresh, ct);
|
||||
(await fresh.ReadValueAsync(Raw(fresh, Scalar), ct)).StatusCode.ShouldBe(StatusCodes.Good);
|
||||
var requestHeader = new RequestHeader { AuthenticationToken = oldAuthentication };
|
||||
var failure = await Should.ThrowAsync<ServiceResultException>(async () =>
|
||||
await fresh.ReadAsync(requestHeader, 0, TimestampsToReturn.Neither,
|
||||
[new ReadValueId { NodeId = Raw(fresh, Scalar), AttributeId = Attributes.Value }], ct));
|
||||
failure.StatusCode.ShouldBe(StatusCodes.BadSessionIdInvalid);
|
||||
requestHeader.AuthenticationToken.ShouldBe(oldAuthentication);
|
||||
(await fresh.BrowseNextAsync(null, false, [browse], ct)).Results[0].StatusCode.ShouldBe(StatusCodes.BadContinuationPointInvalid);
|
||||
var source = rig.Nm.HistorianDataSource.ShouldBeOfType<EventHistoryPagingOverTheWireTests.SqlLikeEventSource>();
|
||||
var readsBefore = source.ReadCount;
|
||||
(await PageAsync(fresh, history, false, ct)).StatusCode.ShouldBe(StatusCodes.BadContinuationPointInvalid);
|
||||
source.ReadCount.ShouldBe(readsBefore, "invalid old tokens must not reach the backend");
|
||||
(await fresh.ReadValueAsync(Raw(fresh, Scalar), ct)).StatusCode.ShouldBe(StatusCodes.Good);
|
||||
await OwnPointsRoundTripAsync(fresh, ct);
|
||||
await fresh.CloseAsync(ct).WaitAsync(TimeSpan.FromSeconds(10), ct);
|
||||
rig.Server.CurrentInstance.SessionManager.GetSessions().ShouldBeEmpty();
|
||||
WriteCloseControl("wire-contract", new { oldAuthStatus = failure.StatusCode.Code, oldBrowseRejected = true, oldHistoryRejected = true,
|
||||
abandonedBrowse = 1, abandonedHistory = 6, freshPositiveRounds = 2 });
|
||||
return weak.ToArray();
|
||||
}
|
||||
|
||||
private static async Task OwnPointsRoundTripAsync(Opc.Ua.Client.ISession session, CancellationToken ct)
|
||||
{
|
||||
var browse = await BrowseAsync(session, ct);
|
||||
browse.IsEmpty.ShouldBeFalse();
|
||||
(await session.BrowseNextAsync(null, false, [browse], ct)).Results[0].StatusCode.ShouldBe(StatusCodes.Good);
|
||||
var history = (await PageAsync(session, default, false, ct)).ContinuationPoint;
|
||||
history.IsEmpty.ShouldBeFalse();
|
||||
var resumed = await PageAsync(session, history, false, ct);
|
||||
resumed.StatusCode.ShouldBe(StatusCodes.Good);
|
||||
resumed.ContinuationPoint.IsEmpty.ShouldBeFalse();
|
||||
(await PageAsync(session, resumed.ContinuationPoint, true, ct)).StatusCode.ShouldBe(StatusCodes.Good);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -32,7 +32,7 @@ namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests;
|
||||
/// No key, certificate, store path, token, or OPC UA payload is written to the JSONL evidence.
|
||||
/// </summary>
|
||||
[Trait("Category", "E2E")]
|
||||
public sealed partial class Sdk2LifecycleSoakTests
|
||||
public sealed class Sdk2LifecycleSoakTests
|
||||
{
|
||||
private const string Scalar = ServerEventRig.RawDeviceFolder + "/SoakScalar";
|
||||
private const string ArrayTag = ServerEventRig.RawDeviceFolder + "/SoakArray";
|
||||
|
||||
-277
@@ -1,277 +0,0 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Opc.Ua;
|
||||
using Opc.Ua.Security.Certificates;
|
||||
using Opc.Ua.Server;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests;
|
||||
|
||||
/// <summary>Verifies host ownership using the real sealed SDK2 server and public manager factories.</summary>
|
||||
public sealed class OpcUaApplicationHostDisposalTests : IDisposable
|
||||
{
|
||||
private static CancellationToken Ct => TestContext.Current.CancellationToken;
|
||||
private readonly string _pki = Path.Combine(Path.GetTempPath(), $"otopcua-sdk2-disposal-{Guid.NewGuid():N}");
|
||||
|
||||
/// <summary>Normal and repeated disposal complete one manager shutdown and terminal server cleanup.</summary>
|
||||
[Fact]
|
||||
public async Task Host_terminally_disposes_its_booted_server_once()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory();
|
||||
var (host, server) = await BootAsync(factory);
|
||||
var manager = factory.Created.ShouldNotBeNull();
|
||||
try
|
||||
{
|
||||
await host.DisposeAsync();
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
await RequireTerminalServerAsync(server);
|
||||
|
||||
await host.DisposeAsync();
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
await RequireTerminalServerAsync(server);
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
/// <summary>Manager disposal during Stop alone does not satisfy the terminal server assertion.</summary>
|
||||
[Fact]
|
||||
public async Task Stop_only_is_distinct_from_terminal_server_disposal()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory();
|
||||
var (host, server) = await BootAsync(factory);
|
||||
var manager = factory.Created.ShouldNotBeNull();
|
||||
try
|
||||
{
|
||||
await server.StopAsync(Ct);
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
var probe = new NonCreatingNodeManagerFactory();
|
||||
var stopped = await Should.ThrowAsync<InvalidOperationException>(() =>
|
||||
server.NodeManagerLifecycle.AddAsync(probe, callerContext: null, Ct).AsTask());
|
||||
stopped.GetType().ShouldBe(typeof(InvalidOperationException));
|
||||
probe.CreateCalls.ShouldBe(0);
|
||||
|
||||
await host.DisposeAsync();
|
||||
await RequireTerminalServerAsync(server);
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
/// <summary>A manager shutdown failure is recorded by the SDK while terminal cleanup still completes.</summary>
|
||||
[Fact]
|
||||
public async Task Shutdown_stage_failure_still_terminally_disposes_the_server()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory { ThrowAfterShutdown = true };
|
||||
var (host, server) = await BootAsync(factory);
|
||||
var manager = factory.Created.ShouldNotBeNull();
|
||||
try
|
||||
{
|
||||
await host.DisposeAsync();
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
ServiceResult.IsBad(server.ServerError).ShouldBeTrue();
|
||||
server.ServerError.ToString().ShouldContain(RecordingSessionManager.ShutdownFailure);
|
||||
await RequireTerminalServerAsync(server);
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
/// <summary>A factory failure after address-space initialization leaves the real server owned for cleanup.</summary>
|
||||
[Fact]
|
||||
public async Task Partial_startup_failure_does_not_strand_the_server()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory { ThrowDuringCreate = true };
|
||||
var host = NewHost(OpcUaHostStart.AllocateFreePort());
|
||||
var server = new OtOpcUaSdkServer { SessionManagerFactory = factory };
|
||||
try
|
||||
{
|
||||
var failure = await Should.ThrowAsync<ServiceResultException>(() => host.StartAsync(server, Ct));
|
||||
failure.StatusCode.ShouldBe(StatusCodes.BadInternalError);
|
||||
failure.InnerResult.ShouldNotBeNull().LocalizedText.Text.ShouldNotBeNull()
|
||||
.ShouldContain(RecordingSessionManagerFactory.StartupFailure);
|
||||
factory.CreateCalls.ShouldBe(1);
|
||||
factory.Created.ShouldBeNull("the sentinel fails before constructing an unowned manager");
|
||||
host.ApplicationInstance.ShouldBeNull();
|
||||
host.Server.ShouldBeNull();
|
||||
await RequireTerminalServerAsync(server);
|
||||
await host.DisposeAsync();
|
||||
await RequireTerminalServerAsync(server);
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
/// <summary>Configuration cancellation before ApplicationInstance adopts the server still releases its host owner.</summary>
|
||||
[Fact]
|
||||
public async Task Canceled_start_before_application_adoption_terminally_disposes_the_server()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory();
|
||||
var host = NewHost(OpcUaHostStart.AllocateFreePort());
|
||||
var server = new OtOpcUaSdkServer { SessionManagerFactory = factory };
|
||||
using var cancellation = new CancellationTokenSource();
|
||||
cancellation.Cancel();
|
||||
try
|
||||
{
|
||||
await Should.ThrowAsync<OperationCanceledException>(() => host.StartAsync(server, cancellation.Token));
|
||||
factory.CreateCalls.ShouldBe(0);
|
||||
factory.Created.ShouldBeNull();
|
||||
host.ApplicationInstance.ShouldBeNull();
|
||||
host.Server.ShouldBeNull();
|
||||
await host.DisposeAsync();
|
||||
await RequireTerminalServerAsync(server);
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
/// <summary>Every concurrent host disposer waits until the one actual manager shutdown is released.</summary>
|
||||
[Fact]
|
||||
public async Task Concurrent_disposers_share_completion_and_one_cleanup_owner()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory();
|
||||
var (host, server) = await BootAsync(factory);
|
||||
var manager = factory.Created.ShouldNotBeNull();
|
||||
manager.BlockShutdown = true;
|
||||
var calls = new List<Task>();
|
||||
try
|
||||
{
|
||||
calls.Add(Task.Run(async () => await host.DisposeAsync(), Ct));
|
||||
await manager.ShutdownEntered.Task.WaitAsync(TimeSpan.FromSeconds(10), Ct);
|
||||
for (var i = 0; i < 3; i++) calls.Add(host.DisposeAsync().AsTask());
|
||||
calls.ShouldAllBe(task => !task.IsCompleted);
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(0);
|
||||
manager.ReleaseShutdown.TrySetResult();
|
||||
await Task.WhenAll(calls).WaitAsync(TimeSpan.FromSeconds(20), Ct);
|
||||
manager.ShutdownCalls.ShouldBe(1);
|
||||
manager.DisposalCalls.ShouldBe(1);
|
||||
await RequireTerminalServerAsync(server);
|
||||
}
|
||||
finally
|
||||
{
|
||||
manager.ReleaseShutdown.TrySetResult();
|
||||
try { await Task.WhenAll(calls).WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None); }
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A terminal host rejects a new real server before invoking its manager factory.</summary>
|
||||
[Fact]
|
||||
public async Task Disposed_host_rejects_start_without_taking_server_ownership()
|
||||
{
|
||||
var factory = new RecordingSessionManagerFactory();
|
||||
var host = NewHost(OpcUaHostStart.AllocateFreePort());
|
||||
var server = new OtOpcUaSdkServer { SessionManagerFactory = factory };
|
||||
try
|
||||
{
|
||||
await host.DisposeAsync();
|
||||
await Should.ThrowAsync<ObjectDisposedException>(() => host.StartAsync(server, Ct));
|
||||
factory.CreateCalls.ShouldBe(0, "the rejected server still belongs to its caller");
|
||||
host.ApplicationInstance.ShouldBeNull();
|
||||
host.Server.ShouldBeNull();
|
||||
}
|
||||
finally { await CleanupAsync(host, server); }
|
||||
}
|
||||
|
||||
private Task<(OpcUaApplicationHost Host, OtOpcUaSdkServer Server)> BootAsync(RecordingSessionManagerFactory factory) =>
|
||||
OpcUaHostStart.StartAsync(NewHost, () => new OtOpcUaSdkServer { SessionManagerFactory = factory }, Ct);
|
||||
|
||||
private OpcUaApplicationHost NewHost(int port) => new(new OpcUaApplicationHostOptions
|
||||
{
|
||||
ApplicationName = "OtOpcUa.SDK2.Disposal", ApplicationUri = "urn:OtOpcUa.SDK2.Disposal",
|
||||
PublicHostname = "localhost", OpcUaPort = port, PkiStoreRoot = _pki, AllowAnonymous = false,
|
||||
}, NullLogger<OpcUaApplicationHost>.Instance);
|
||||
|
||||
private static async Task RequireTerminalServerAsync(OtOpcUaSdkServer server)
|
||||
{
|
||||
// The public lifecycle checks terminal disposal before considering or invoking this factory.
|
||||
var probe = new NonCreatingNodeManagerFactory();
|
||||
var disposed = await Should.ThrowAsync<ObjectDisposedException>(() =>
|
||||
server.NodeManagerLifecycle.AddAsync(probe, callerContext: null, CancellationToken.None).AsTask());
|
||||
disposed.GetType().ShouldBe(typeof(ObjectDisposedException));
|
||||
probe.CreateCalls.ShouldBe(0);
|
||||
}
|
||||
|
||||
private static async Task CleanupAsync(OpcUaApplicationHost host, OtOpcUaSdkServer server)
|
||||
{
|
||||
try { await host.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None); }
|
||||
finally
|
||||
{
|
||||
// RED assertions still release the actual test-owned server; never dispose a manager manually.
|
||||
await server.DisposeAsync().AsTask().WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class RecordingSessionManagerFactory : ISessionManagerFactory
|
||||
{
|
||||
internal const string StartupFailure = "controlled SDK2 partial startup";
|
||||
private int _createCalls;
|
||||
internal int CreateCalls => Volatile.Read(ref _createCalls);
|
||||
internal RecordingSessionManager? Created { get; private set; }
|
||||
internal bool ThrowDuringCreate { get; init; }
|
||||
internal bool ThrowAfterShutdown { get; init; }
|
||||
|
||||
public ISessionManager Create(IServerInternal server, ApplicationConfiguration configuration,
|
||||
TimeProvider timeProvider, Func<string, Certificate?> serverCertificateProvider)
|
||||
{
|
||||
Interlocked.Increment(ref _createCalls);
|
||||
if (ThrowDuringCreate) throw new InvalidOperationException(StartupFailure);
|
||||
return Created = new RecordingSessionManager(server, configuration, timeProvider)
|
||||
{
|
||||
ThrowAfterShutdown = ThrowAfterShutdown,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class RecordingSessionManager(IServerInternal server, ApplicationConfiguration configuration, TimeProvider timeProvider)
|
||||
: SessionManager(server, configuration, timeProvider)
|
||||
{
|
||||
internal const string ShutdownFailure = "controlled SDK2 manager shutdown failure";
|
||||
private int _shutdownCalls;
|
||||
private int _disposalCalls;
|
||||
internal int ShutdownCalls => Volatile.Read(ref _shutdownCalls);
|
||||
internal int DisposalCalls => Volatile.Read(ref _disposalCalls);
|
||||
internal bool ThrowAfterShutdown { get; init; }
|
||||
internal bool BlockShutdown { get; set; }
|
||||
internal TaskCompletionSource ShutdownEntered { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
internal TaskCompletionSource ReleaseShutdown { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
|
||||
public override async ValueTask ShutdownAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
Interlocked.Increment(ref _shutdownCalls);
|
||||
if (BlockShutdown)
|
||||
{
|
||||
ShutdownEntered.TrySetResult();
|
||||
await ReleaseShutdown.Task.WaitAsync(TimeSpan.FromSeconds(20), CancellationToken.None);
|
||||
}
|
||||
await base.ShutdownAsync(cancellationToken);
|
||||
if (ThrowAfterShutdown) throw new InvalidOperationException(ShutdownFailure);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing) Interlocked.Increment(ref _disposalCalls);
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class NonCreatingNodeManagerFactory : INodeManagerFactory
|
||||
{
|
||||
private int _createCalls;
|
||||
internal int CreateCalls => Volatile.Read(ref _createCalls);
|
||||
public ArrayOf<string> NamespacesUris => [];
|
||||
public INodeManager Create(IServerInternal server, ApplicationConfiguration configuration)
|
||||
{
|
||||
Interlocked.Increment(ref _createCalls);
|
||||
throw new InvalidOperationException("The terminal lifecycle probe must not create a node manager.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Removes only this test's private fixture after bounded server cleanup.</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_pki)) Directory.Delete(_pki, true);
|
||||
}
|
||||
}
|
||||
+4
-15
@@ -131,24 +131,13 @@ public sealed class OpcUaPublishActorRebuildTests : RuntimeActorTestBase
|
||||
var actor = Sys.ActorOf(OpcUaPublishActor.PropsForTests(
|
||||
sink: sink, dbFactory: db, applier: applier));
|
||||
|
||||
// EF is recorded before the first apply's NodeAdded announcement. Wait for each reply so
|
||||
// the snapshot includes every first-apply call and the second apply has actually finished.
|
||||
var first = Rebuild(dep) with { ReportOutcome = true };
|
||||
actor.Tell(first);
|
||||
var firstCompleted = ExpectMsg<OpcUaPublishActor.RebuildCompleted>(PresenceBudget,
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
firstCompleted.Correlation.ShouldBe(first.Correlation);
|
||||
firstCompleted.Degraded.ShouldBeFalse();
|
||||
sink.Calls.ShouldContain("EF:eq-1");
|
||||
actor.Tell(Rebuild(dep));
|
||||
AwaitAssert(() => sink.Calls.ShouldContain("EF:eq-1"), duration: PresenceBudget, cancellationToken: TestContext.Current.CancellationToken);
|
||||
sink.RebuildCalls.ShouldBe(0); // PureAdd — no full rebuild
|
||||
var callsAfterFirst = sink.Calls.Count;
|
||||
|
||||
var second = Rebuild(dep) with { ReportOutcome = true };
|
||||
actor.Tell(second);
|
||||
var secondCompleted = ExpectMsg<OpcUaPublishActor.RebuildCompleted>(PresenceBudget,
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
secondCompleted.Correlation.ShouldBe(second.Correlation);
|
||||
secondCompleted.Degraded.ShouldBeFalse();
|
||||
actor.Tell(Rebuild(dep));
|
||||
Thread.Sleep(200);
|
||||
// Same composition ⇒ plan IsEmpty ⇒ applier + materialise passes not run again.
|
||||
sink.Calls.Count.ShouldBe(callsAfterFirst);
|
||||
sink.RebuildCalls.ShouldBe(0);
|
||||
|
||||
Reference in New Issue
Block a user