mirror of
https://github.com/lucannez64/darling-lol.git
synced 2026-10-26 19:47:42 +00:00
Make the CFHost cancel probe wait for delivery and reject completed lookups
Wait up to 2 s for the cancellation callback instead of one 50 ms run-loop pass, count only callbacks without stored addresses so a completed lookup cannot pass as a cancellation, print the failing stage, and have the runner require the exact success line since Darling can exit zero after a trap. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
67626612ac
commit
72093a1b58
3 files changed
+27
-8
No files matched your search
+4
-2
@@ -406,7 +406,9 @@ python3 build/runtime/tools/run-riot-native-check.py riot-cfhost-cancel-check
|
|||||||
|
|
||||||
Run against the installed CFNetwork override. Expect
|
Run against the installed CFNetwork override. Expect
|
||||||
`CFHOST_CANCEL_CHECK cancel callback lifetime repeated pass=1`. The unpatched
|
`CFHOST_CANCEL_CHECK cancel callback lifetime repeated pass=1`. The unpatched
|
||||||
library traps in `CFRetain(NULL)`; the runner checks the success marker because
|
library traps in `CFRetain(NULL)`; the runner requires the exact success line because
|
||||||
Darling can return status zero even when the guest traps. The probe uses localhost
|
Darling can return status zero even when the guest traps. The probe uses localhost
|
||||||
and exercises 100 cancellations with both retained and early-released caller
|
and exercises 100 cancellations with both retained and early-released caller
|
||||||
references, without launching or inspecting Riot.
|
references, without launching or inspecting Riot. A failure prints
|
||||||
|
`CFHOST_CANCEL_CHECK fail stage=...`; `unexpected-callback` means a completed
|
||||||
|
lookup arrived instead of the cancellation.
|
||||||
@@ -2,11 +2,22 @@
|
|||||||
#include <CFNetwork/CFHost.h>
|
#include <CFNetwork/CFHost.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static unsigned callbacks;
|
static unsigned callbacks, unexpected;
|
||||||
static void completed(CFHostRef host, CFHostInfoType type,
|
static void completed(CFHostRef host, CFHostInfoType type,
|
||||||
const CFStreamError *error, void *info) {
|
const CFStreamError *error, void *info) {
|
||||||
if (host && type == kCFHostAddresses && info == &callbacks)
|
/* A cancellation stores no addresses; a completed lookup always does. */
|
||||||
|
Boolean resolved = false;
|
||||||
|
if (host) CFHostGetAddressing(host, &resolved);
|
||||||
|
if (host && type == kCFHostAddresses && info == &callbacks && !resolved)
|
||||||
++callbacks;
|
++callbacks;
|
||||||
|
else
|
||||||
|
++unexpected;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fail(const char *stage, unsigned i) {
|
||||||
|
printf("CFHOST_CANCEL_CHECK fail stage=%s iteration=%u callbacks=%u unexpected=%u\n",
|
||||||
|
stage, i, callbacks, unexpected);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
@@ -14,14 +25,17 @@ int main(void) {
|
|||||||
for (unsigned i = 0; i < 100; ++i) {
|
for (unsigned i = 0; i < 100; ++i) {
|
||||||
CFHostRef host = CFHostCreateWithName(NULL, CFSTR("localhost"));
|
CFHostRef host = CFHostCreateWithName(NULL, CFSTR("localhost"));
|
||||||
CFStreamError error = {0};
|
CFStreamError error = {0};
|
||||||
if (!host || !CFHostSetClient(host, completed, &context)) return 1;
|
if (!host || !CFHostSetClient(host, completed, &context)) return fail("client", i);
|
||||||
CFHostScheduleWithRunLoop(host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
CFHostScheduleWithRunLoop(host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||||
if (!CFHostStartInfoResolution(host, kCFHostAddresses, &error)) return 2;
|
if (!CFHostStartInfoResolution(host, kCFHostAddresses, &error)) return fail("start", i);
|
||||||
CFHostCancelInfoResolution(host, kCFHostAddresses);
|
CFHostCancelInfoResolution(host, kCFHostAddresses);
|
||||||
/* The cancel source must keep its host alive until delivery. */
|
/* The cancel source must keep its host alive until delivery. */
|
||||||
if (i % 2) CFRelease(host);
|
if (i % 2) CFRelease(host);
|
||||||
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.05, false);
|
CFAbsoluteTime deadline = CFAbsoluteTimeGetCurrent() + 2.0;
|
||||||
if (callbacks != i + 1) return 3;
|
while (callbacks != i + 1 && !unexpected && CFAbsoluteTimeGetCurrent() < deadline)
|
||||||
|
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.05, true);
|
||||||
|
if (unexpected) return fail("unexpected-callback", i);
|
||||||
|
if (callbacks != i + 1) return fail("cancel-callback", i);
|
||||||
if (!(i % 2)) CFRelease(host);
|
if (!(i % 2)) CFRelease(host);
|
||||||
}
|
}
|
||||||
puts("CFHOST_CANCEL_CHECK cancel callback lifetime repeated pass=1");
|
puts("CFHOST_CANCEL_CHECK cancel callback lifetime repeated pass=1");
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ with tempfile.TemporaryFile() as output:
|
|||||||
if (args.check == "riot-running-application-check" and
|
if (args.check == "riot-running-application-check" and
|
||||||
line != "RUNNING_APP found=1 activated=1 missing=1"):
|
line != "RUNNING_APP found=1 activated=1 missing=1"):
|
||||||
result = 1
|
result = 1
|
||||||
|
if (args.check == "riot-cfhost-cancel-check" and
|
||||||
|
line != "CFHOST_CANCEL_CHECK cancel callback lifetime repeated pass=1"):
|
||||||
|
result = 1
|
||||||
if (args.check == "riot-mach-exception-state-check" and
|
if (args.check == "riot-mach-exception-state-check" and
|
||||||
line != "MACH_EXCEPTION_STATE state=1 identity=1 handled=2 server=1"):
|
line != "MACH_EXCEPTION_STATE state=1 identity=1 handled=2 server=1"):
|
||||||
result = 1
|
result = 1
|
||||||
|
|||||||
Reference in new issue
Block a user