app.dhover×446 error×24all
// macOS/AppKit F17 demo — threading probes (../../../features/f17-threading.md).
// Deliberately violates (and obeys) AppKit's main-thread rule and records exactly
// what breaks. Five --probe=N run modes, each ending in a verdict line
// (`probe n=… result=ok|error|crash|deadlock|silent detail=…`) that survives any
// outcome: fatal-signal handlers (SIGSEGV/SIGBUS/SIGILL/SIGABRT/SIGTRAP) and an
// NSUncaughtExceptionHandler turn crashes into a flushed verdict + _exit(0) —
// capturing AppKit's exact assert/exception text — and a SIGALRM watchdog converts
// hangs into result=deadlock. The no-argument run (what CI executes) spawns every
// probe TWICE as a fresh fork+exec'd child (fork-without-exec is forbidden to
// Objective-C apps on macOS), so a crashed probe can never poison the next and the
// parent always reports.
//
//   1  NSWindow created on a SECOND thread (pthread), main thread pumps events.
//   2  [NSApp run] on main; AFTER the loop starts, a worker creates a window.
//   3  The sanctioned pattern: worker computes, marshals to main via BOTH
//      performSelectorOnMainThread:withObject:waitUntilDone: and
//      dispatch_async_f(dispatch_get_main_queue()) — proves both land on main.
//   4  Render from a second thread: (a) worker fills the CPU buffer and marshals
//      setNeedsDisplay: to main vs (b) DIRECT cross-thread setNeedsDisplay: and
//      lockFocusIfCanDraw + CGContext drawing from the worker.
//   5  NSPasteboard write/read + NSEvent post from a worker thread.
//
// Headless-safe: prints `SKIP:` and exits 0 when no window server is reachable.
module 
(module) app
app
;
import
(package) core
core
.
(module) core.attribute

This module contains UDA's (User Defined Attributes) either used in the runtime or special UDA's recognized by compiler.

Attribute Name, Linkage, Description

gnuAbiTag, C++, Declares an ABI tag on a C++ symbol. mustuse,, Ensures that values of a struct or union type are not discarded. optional, Objective-C, Makes an Objective-C interface method optional. selector, Objective-C, Attaches an Objective-C selector to a method. standalone,, Marks a shared module constructor as not depending on any other module constructor being run first. weak,, Specifies that a global symbol should be emitted with weak linkage.

Source

core/attribute.d

@copyrightCopyright Jacob Carlborg 2015.@licenseBoost License 1.0@authorsJacob Carlborg
attribute
: selector;
module `core.attribute` import `selector` not found
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdio

D header file for C99 <stdio.h>

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdio.h.html, stdio.h

Source

core/stdc/stdio.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly, Alex Rønne Petersen@standardsISO/IEC 9899:1999 (E)
stdio
:
(alias) app.printf = int core.stdc.stdio.printf(scope const(char*) format, scope const ...) nothrow @nogc
printf
,
(alias) app.fprintf = int core.stdc.stdio.fprintf(shared(core.stdc.stdio._IO_FILE)* stream, scope const(char*) format, scope const ...) nothrow @nogc
fprintf
,
(alias) app.snprintf = int core.stdc.stdio.snprintf(scope char* s, ulong n, scope const(char*) format, scope const ...) nothrow @nogc
snprintf
,
(alias shared global) app.stderr = shared(core.stdc.stdio._IO_FILE*) core.stdc.stdio.stderr
stderr
,
(alias) app.fflush = int core.stdc.stdio.fflush(shared(core.stdc.stdio._IO_FILE)* stream) nothrow @nogc @trusted
fflush
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.stdlib

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/stdlib.h.html, stdlib.h

Source

core/stdc/stdlib.d

@copyrightCopyright Sean Kelly 2005 - 2014.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
stdlib
:
(alias) app.getenv = char* core.stdc.stdlib.getenv(scope const(char*) name) nothrow @nogc
getenv
,
(alias) app.atoi = int core.stdc.stdlib.atoi(scope const(char*) nptr) nothrow @nogc
atoi
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.string

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h

Source

core/stdc/string.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
string
:
(alias) app.strncmp = int core.stdc.string.strncmp(scope const(char*) s1, scope const(char*) s2, ulong n) pure nothrow @nogc
strncmp
,
(alias) app.strlen = ulong core.stdc.string.strlen(scope const(char*) s) pure nothrow @nogc
strlen
;
import instrument : instr, instrInit, instrNowUs;
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
unable to read module `instrument` Expected 'instrument.d' or 'instrument/package.d' in one of the following import paths:
import objc.autorelease : autoreleasepool_push, autoreleasepool_pop; // objective-d
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
unable to read module `autorelease` Expected 'objc/autorelease.d' or 'objc/autorelease/package.d' in one of the following import paths:
import objc.rt : SEL;
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
unable to read module `rt` Expected 'objc/rt.d' or 'objc/rt/package.d' in one of the following import paths:
// --- Geometry ---------------------------------------------------------------------- extern (C) struct
(struct) app.NSPoint
NSPoint
{ double
(field) double app.NSPoint.x
x
,
(field) double app.NSPoint.y
y
;
} extern (C) struct
(struct) app.NSSize
NSSize
{ double
(field) double app.NSSize.width
width
,
(field) double app.NSSize.height
height
;
} extern (C) struct
(struct) app.NSRect
NSRect
{
(struct) app.NSPoint
NSPoint
(field) app.NSPoint app.NSRect.origin
origin
;
(struct) app.NSSize
NSSize
(field) app.NSSize app.NSRect.size
size
;
} // --- POSIX / CoreGraphics / libdispatch -------------------------------------------- extern (C) nothrow @nogc { uint
uint app.CGMainDisplayID() nothrow @nogc
CGMainDisplayID
();
void
void app.CFRelease(void* obj) nothrow @nogc
CFRelease
(void*
(parameter) void* obj
obj
);
void*
void* app.CGSessionCopyCurrentDictionary() nothrow @nogc
CGSessionCopyCurrentDictionary
();
void*
void* app.CFStringCreateWithCString(void* alloc, const(char)* s, uint encoding) nothrow @nogc
CFStringCreateWithCString
(void*
(parameter) void* alloc
alloc
, const(char)*
(parameter) const(char)* s
s
, uint
(parameter) uint encoding
encoding
);
void*
void* app.CFDictionaryGetValue(void* dict, void* key) nothrow @nogc
CFDictionaryGetValue
(void*
(parameter) void* dict
dict
, void*
(parameter) void* key
key
);
ubyte
ubyte app.CFBooleanGetValue(void* b) nothrow @nogc
CFBooleanGetValue
(void*
(parameter) void* b
b
);
void
void app.CGContextSetRGBFillColor(void* ctx, double r, double g, double b, double a) nothrow @nogc
CGContextSetRGBFillColor
(void*
(parameter) void* ctx
ctx
, double
(parameter) double r
r
, double
(parameter) double g
g
, double
(parameter) double b
b
, double
(parameter) double a
a
);
void
void app.CGContextFillRect(void* ctx, app.NSRect rect) nothrow @nogc
CGContextFillRect
(void*
(parameter) void* ctx
ctx
,
(struct) app.NSRect
NSRect
(parameter) app.NSRect rect
rect
);
int
int app.pthread_create(void** thread, const(void)* attr, extern (C) void* function(void*), void* arg) nothrow @nogc
pthread_create
(void**
(parameter) void** thread
thread
, const(void)*
(parameter) const(void)* attr
attr
,
void* function(void*), void*
(parameter) void* arg
arg
);
int
int app.pthread_join(void* thread, void** retval) nothrow @nogc
pthread_join
(void*
(parameter) void* thread
thread
, void**
(parameter) void** retval
retval
);
int
int app.pthread_main_np() nothrow @nogc
pthread_main_np
();
int
int app.usleep(uint usec) nothrow @nogc
usleep
(uint
(parameter) uint usec
usec
);
uint
uint app.alarm(uint seconds) nothrow @nogc
alarm
(uint
(parameter) uint seconds
seconds
);
void function(int)
void function(int) app.signal(int sig, extern (C) void function(int) handler) nothrow @nogc
signal
(int
(parameter) int sig
sig
, void function(int)
(parameter) extern (C) void function(int) handler
handler
);
void
void app._exit(int code) nothrow @nogc
_exit
(int
(parameter) int code
code
);
long
long app.write(int fd, const(void)* buf, ulong n) nothrow @nogc
write
(int
(parameter) int fd
fd
, const(void)*
(parameter) const(void)* buf
buf
,
(alias) object.size_t = ulong
size_t
(parameter) ulong n
n
);
int
int app.fork() nothrow @nogc
fork
();
int
int app.execv(const(char)* path, const(char*)* argv) nothrow @nogc
execv
(const(char)*
(parameter) const(char)* path
path
, const(char*)*
(parameter) const(char*)* argv
argv
);
int
int app.waitpid(int pid, int* status, int options) nothrow @nogc
waitpid
(int
(parameter) int pid
pid
, int*
(parameter) int* status
status
, int
(parameter) int options
options
);
// dispatch_get_main_queue() is a macro for &_dispatch_main_q. extern __gshared void*
(__gshared global) void* app._dispatch_main_q
_dispatch_main_q
;
void
void app.dispatch_async_f(void* queue, void* context, extern (C) void function(void*) work) nothrow @nogc
dispatch_async_f
(void*
(parameter) void* queue
queue
, void*
(parameter) void* context
context
, void function(void*)
(parameter) extern (C) void function(void*) work
work
);
alias
(alias) app.NSUncaughtExceptionHandler = extern (C) void function(void* exception) nothrow @nogc
NSUncaughtExceptionHandler
= void function(void*
(parameter) void* exception
exception
);
void
void app.NSSetUncaughtExceptionHandler(extern (C) void function(void* exception) nothrow @nogc h) nothrow @nogc
NSSetUncaughtExceptionHandler
(
(alias) app.NSUncaughtExceptionHandler = extern (C) void function(void* exception) nothrow @nogc
NSUncaughtExceptionHandler
(parameter) extern (C) void function(void* exception) nothrow @nogc h
h
);
} enum uint
(constant) uint app.kCFStringEncodingUTF8 = 134217984u
kCFStringEncodingUTF8
= 0x08000100;
enum : int {
(enum value) app.SIGILL = 4
SIGILL
= 4,
(enum value) app.SIGABRT = 6
SIGABRT
= 6,
(enum value) app.SIGBUS = 10
SIGBUS
= 10,
(enum value) app.SIGSEGV = 11
SIGSEGV
= 11,
(enum value) app.SIGALRM = 14
SIGALRM
= 14,
(enum value) app.SIGTRAP = 5
SIGTRAP
= 5,
} void
void app.logSessionLockState()
logSessionLockState
()
{ void*
(local variable) void* dict
dict
=
void* app.CGSessionCopyCurrentDictionary() nothrow @nogc
CGSessionCopyCurrentDictionary
();
if (
(local variable) void* dict
dict
is null)
{ instr("session", "lock_state=no_session_dictionary"); return; } void*
(local variable) void* kLocked
kLocked
=
void* app.CFStringCreateWithCString(void* alloc, const(char)* s, uint encoding) nothrow @nogc
CFStringCreateWithCString
(null, "CGSSessionScreenIsLocked",
(constant) uint app.kCFStringEncodingUTF8 = 134217984u
kCFStringEncodingUTF8
);
void*
(local variable) void* locked
locked
=
void* app.CFDictionaryGetValue(void* dict, void* key) nothrow @nogc
CFDictionaryGetValue
(
(local variable) void* dict
dict
,
(local variable) void* kLocked
kLocked
);
instr("session", "screen_locked=%d", locked !is null && CFBooleanGetValue(locked) ? 1 : 0);
void app.CFRelease(void* obj) nothrow @nogc
CFRelease
(
(local variable) void* kLocked
kLocked
);
void app.CFRelease(void* obj) nothrow @nogc
CFRelease
(
(local variable) void* dict
dict
);
} // --- AppKit class declarations ----------------------------------------------------- extern (Objective-C): extern class
(class) app.NSObject
NSObject
class `app.NSObject` Objective-C classes not supported
{ void
app.NSObject.performSelectorOnMainThread
performSelectorOnMainThread
(SEL sel,
(class) app.NSObject
NSObject
(parameter) NSObject arg
arg
, bool wait)
@selector("performSelectorOnMainThread:withObject:waitUntilDone:"); } extern class
(class) app.NSString
NSString
:
(class) app.NSObject
NSObject
class `app.NSString` Objective-C classes not supported
{ static
(class) app.NSString
NSString
app.NSString app.NSString.alloc()
alloc
() @selector("alloc");
(class) app.NSString
NSString
app.NSString app.NSString.initWithUTF8String(const(char)* s)
initWithUTF8String
(const(char)*
(parameter) const(char)* s
s
) @selector("initWithUTF8String:");
const(char)*
const(char)* app.NSString.UTF8String()
UTF8String
() @selector("UTF8String");
} extern class
(class) app.NSException
NSException
:
(class) app.NSObject
NSObject
class `app.NSException` Objective-C classes not supported
{
(class) app.NSString
NSString
app.NSString app.NSException.name()
name
() @selector("name");
(class) app.NSString
NSString
app.NSString app.NSException.reason()
reason
() @selector("reason");
} extern class
(class) app.NSPasteboard
NSPasteboard
:
(class) app.NSObject
NSObject
class `app.NSPasteboard` Objective-C classes not supported
{ static
(class) app.NSPasteboard
NSPasteboard
app.NSPasteboard app.NSPasteboard.generalPasteboard()
generalPasteboard
() @selector("generalPasteboard");
long
long app.NSPasteboard.changeCount()
changeCount
() @selector("changeCount");
long
long app.NSPasteboard.clearContents()
clearContents
() @selector("clearContents");
bool
bool app.NSPasteboard.setString(app.NSString s, app.NSString type)
setString
(
(class) app.NSString
NSString
(parameter) app.NSString s
s
,
(class) app.NSString
NSString
(parameter) app.NSString type
type
) @selector("setString:forType:");
(class) app.NSString
NSString
app.NSString app.NSPasteboard.stringForType(app.NSString type)
stringForType
(
(class) app.NSString
NSString
(parameter) app.NSString type
type
) @selector("stringForType:");
} extern class
(class) app.NSDate
NSDate
:
(class) app.NSObject
NSObject
class `app.NSDate` Objective-C classes not supported
{ static
(class) app.NSDate
NSDate
app.NSDate app.NSDate.distantPast()
distantPast
() @selector("distantPast");
} extern class
(class) app.NSEvent
NSEvent
:
(class) app.NSObject
NSObject
class `app.NSEvent` Objective-C classes not supported
{ static
(class) app.NSEvent
NSEvent
app.NSEvent app.NSEvent.otherEventWithType(long type, app.NSPoint location, ulong modifierFlags, double timestamp, long windowNumber, app.NSObject context, short subtype, long data1, long data2)
otherEventWithType
(long
(parameter) long type
type
,
(struct) app.NSPoint
NSPoint
(parameter) app.NSPoint location
location
, ulong
(parameter) ulong modifierFlags
modifierFlags
,
double
(parameter) double timestamp
timestamp
, long
(parameter) long windowNumber
windowNumber
,
(class) app.NSObject
NSObject
(parameter) app.NSObject context
context
, short
(parameter) short subtype
subtype
,
long
(parameter) long data1
data1
, long
(parameter) long data2
data2
)
@selector("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:"); long
long app.NSEvent.type()
type
() @selector("type");
short
short app.NSEvent.subtype()
subtype
() @selector("subtype");
long
long app.NSEvent.data1()
data1
() @selector("data1");
} extern class
(class) app.NSTimer
NSTimer
:
(class) app.NSObject
NSObject
class `app.NSTimer` Objective-C classes not supported
{ static
(class) app.NSTimer
NSTimer
app.NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(double interval,
(class) app.NSObject
NSObject
target,
SEL sel,
(class) app.NSObject
NSObject
userInfo, bool repeats)
@selector("scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:"); } extern class
(class) app.NSApplication
NSApplication
:
(class) app.NSObject
NSObject
class `app.NSApplication` Objective-C classes not supported
{ static
(class) app.NSApplication
NSApplication
app.NSApplication app.NSApplication.sharedApplication()
sharedApplication
() @selector("sharedApplication");
void
void app.NSApplication.setActivationPolicy(long policy)
setActivationPolicy
(long
(parameter) long policy
policy
) @selector("setActivationPolicy:");
void
void app.NSApplication.run()
run
() @selector("run");
void
void app.NSApplication.stop(app.NSObject sender)
stop
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("stop:");
void
void app.NSApplication.postEvent(app.NSEvent event, bool atStart)
postEvent
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent event
event
, bool
(parameter) bool atStart
atStart
) @selector("postEvent:atStart:");
void
void app.NSApplication.sendEvent(app.NSEvent event)
sendEvent
(
(class) app.NSEvent
NSEvent
(parameter) app.NSEvent event
event
) @selector("sendEvent:");
(class) app.NSEvent
NSEvent
app.NSEvent app.NSApplication.nextEventMatchingMask(ulong mask, app.NSDate untilDate, app.NSString inMode, bool dequeue)
nextEventMatchingMask
(ulong
(parameter) ulong mask
mask
,
(class) app.NSDate
NSDate
(parameter) app.NSDate untilDate
untilDate
,
(class) app.NSString
NSString
(parameter) app.NSString inMode
inMode
,
bool
(parameter) bool dequeue
dequeue
)
@selector("nextEventMatchingMask:untilDate:inMode:dequeue:"); } extern class
(class) app.NSGraphicsContext
NSGraphicsContext
:
(class) app.NSObject
NSObject
class `app.NSGraphicsContext` Objective-C classes not supported
{ static
(class) app.NSGraphicsContext
NSGraphicsContext
app.NSGraphicsContext app.NSGraphicsContext.currentContext()
currentContext
() @selector("currentContext");
void*
void* app.NSGraphicsContext.CGContext()
CGContext
() @selector("CGContext");
} extern class
(class) app.NSView
NSView
:
(class) app.NSObject
NSObject
class `app.NSView` Objective-C classes not supported
{
(struct) app.NSRect
NSRect
app.NSRect app.NSView.bounds()
bounds
() @selector("bounds");
void
void app.NSView.setNeedsDisplay(bool flag)
setNeedsDisplay
(bool
(parameter) bool flag
flag
) @selector("setNeedsDisplay:");
bool
bool app.NSView.lockFocusIfCanDraw()
lockFocusIfCanDraw
() @selector("lockFocusIfCanDraw");
void
void app.NSView.unlockFocus()
unlockFocus
() @selector("unlockFocus");
} extern class
(class) app.NSWindow
NSWindow
:
(class) app.NSObject
NSObject
class `app.NSWindow` Objective-C classes not supported
{
(class) app.NSWindow
NSWindow
app.NSWindow app.NSWindow.initWithContentRect(app.NSRect contentRect, ulong styleMask, ulong backing, bool defer)
initWithContentRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect contentRect
contentRect
, ulong
(parameter) ulong styleMask
styleMask
,
ulong
(parameter) ulong backing
backing
, bool
(parameter) bool defer
defer
) @selector("initWithContentRect:styleMask:backing:defer:");
void
void app.NSWindow.setTitle(app.NSString title)
setTitle
(
(class) app.NSString
NSString
(parameter) app.NSString title
title
) @selector("setTitle:");
void
void app.NSWindow.setContentView(app.NSObject view)
setContentView
(
(class) app.NSObject
NSObject
(parameter) app.NSObject view
view
) @selector("setContentView:");
void
void app.NSWindow.setReleasedWhenClosed(bool b)
setReleasedWhenClosed
(bool
(parameter) bool b
b
) @selector("setReleasedWhenClosed:");
void
void app.NSWindow.makeKeyAndOrderFront(app.NSObject sender)
makeKeyAndOrderFront
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("makeKeyAndOrderFront:");
void
void app.NSWindow.orderOut(app.NSObject sender)
orderOut
(
(class) app.NSObject
NSObject
(parameter) app.NSObject sender
sender
) @selector("orderOut:");
long
long app.NSWindow.windowNumber()
windowNumber
() @selector("windowNumber");
} class
(class) app.PlainWindow
PlainWindow
:
(class) app.NSWindow
NSWindow
class `app.PlainWindow` Objective-C classes not supported
{ static
(class) app.PlainWindow
PlainWindow
app.PlainWindow app.PlainWindow.alloc()
alloc
() @selector("alloc");
} // Probe 4's view: drawRect logs which thread it runs on and blits g_fill. class
(class) app.ProbeView
ProbeView
:
(class) app.NSView
NSView
class `app.ProbeView` Objective-C classes not supported
{ static
(class) app.ProbeView
ProbeView
app.ProbeView app.ProbeView.alloc()
alloc
() @selector("alloc");
(class) app.ProbeView
ProbeView
app.ProbeView app.ProbeView.initWithFrame(app.NSRect frame)
initWithFrame
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect frame
frame
) @selector("initWithFrame:");
void
void app.ProbeView.drawRect(app.NSRect dirtyRect)
drawRect
(
(struct) app.NSRect
NSRect
(parameter) app.NSRect dirtyRect
dirtyRect
) @selector("drawRect:")
{ ++g_draws; instr("draw_rect", "n=%d main_thread=%d fill=%.2f", g_draws, pthread_main_np(), g_fill); void*
_error_ ctx
ctx
= NSGraphicsContext.
NSGraphicsContext.currentContext
currentContext
().
NSGraphicsContext.currentContext().CGContext
CGContext
();
CGContextSetRGBFillColor(ctx, g_fill, 0.3, 0.5, 1); CGContextFillRect(ctx, this.
this.bounds
bounds
());
} } // Main-thread marshaling target for probe 3 (performSelectorOnMainThread:). class
(class) app.Marshal
Marshal
:
(class) app.NSObject
NSObject
class `app.Marshal` Objective-C classes not supported
{ static
(class) app.Marshal
Marshal
app.Marshal app.Marshal.alloc()
alloc
() @selector("alloc");
(class) app.Marshal
Marshal
app.Marshal app.Marshal.init()
init
() @selector("init");
void
void app.Marshal.report(app.NSObject arg)
report
(
(class) app.NSObject
NSObject
(parameter) app.NSObject arg
arg
) @selector("report:")
{ g_perfSelOnMain = pthread_main_np(); instr("marshal", "route=performSelectorOnMainThread main_thread=%d", g_perfSelOnMain); maybeFinishProbe3(); } void
void app.Marshal.tick(app.NSTimer t)
tick
(
(class) app.NSTimer
NSTimer
(parameter) app.NSTimer t
t
) @selector("tick:")
{ onTick(); } } extern (D): // back to D linkage enum
(constant) int app.NSApplicationActivationPolicyRegular = 0
NSApplicationActivationPolicyRegular
= 0;
enum ulong
(constant) ulong app.NSWindowStyleMaskTitled = 1LU
NSWindowStyleMaskTitled
= 1;
enum ulong
(constant) ulong app.NSBackingStoreBuffered = 2LU
NSBackingStoreBuffered
= 2;
enum long
(constant) long app.NSEventTypeApplicationDefined = 15L
NSEventTypeApplicationDefined
= 15;
__gshared
(class) app.NSApplication
NSApplication
(__gshared global) app.NSApplication app.g_app
g_app
;
__gshared
(class) app.NSWindow
NSWindow
(__gshared global) app.NSWindow app.g_win
g_win
;
__gshared
(class) app.ProbeView
ProbeView
(__gshared global) app.ProbeView app.g_view
g_view
;
__gshared
(class) app.Marshal
Marshal
(__gshared global) app.Marshal app.g_marshal
g_marshal
;
__gshared int
(__gshared global) int app.g_probe
g_probe
;
__gshared int
(__gshared global) int app.g_ticks
g_ticks
;
__gshared int
(__gshared global) int app.g_draws
g_draws
;
__gshared int
(__gshared global) int app.g_perfSelOnMain
g_perfSelOnMain
= -1;
__gshared int
(__gshared global) int app.g_dispatchOnMain
g_dispatchOnMain
= -1;
__gshared bool
(__gshared global) bool app.g_workerDone
g_workerDone
;
__gshared bool
(__gshared global) bool app.g_verdictWritten
g_verdictWritten
;
__gshared double
(__gshared global) double app.g_fill
g_fill
= 0.2;
__gshared char[256]
(__gshared global) char[256] app.g_detail
g_detail
;
(class) app.NSString
NSString
app.NSString app.nsstr(const(char)* s)
nsstr
(const(char)*
(parameter) const(char)* s
s
)
{ return NSString.
NSString.alloc
alloc
().
NSString.alloc().initWithUTF8String
initWithUTF8String
(s);
} // --- Verdicts that survive crashes --------------------------------------------------- // Async-signal-safe: snprintf into a static buffer + write(2). void
void app.verdict(const(char)* result, const(char)* detail) nothrow @nogc
verdict
(const(char)*
(parameter) const(char)* result
result
, const(char)*
(parameter) const(char)* detail
detail
) nothrow @nogc
{ if (g_verdictWritten) return; g_verdictWritten = true; __gshared char[512]
_error_ buf
buf
;
immutable
_error_ n
n
= snprintf(buf.ptr, buf.length,
"%llu APPKIT_F17 probe n=%d result=%s detail=%s\n", instrNowUs(), g_probe, result, detail); write(2, buf.ptr, n > 0 ? n : 0); } extern (C) void
void app.onFatalSignal(int sig) nothrow @nogc
onFatalSignal
(int
(parameter) int sig
sig
) nothrow @nogc
{ __gshared char[128]
_error_ d
d
;
snprintf(d.ptr, d.length, "fatal_signal_%d%s", sig, sig == SIGABRT ? "_abort(see_exception_log_above)".ptr : "".ptr); verdict("crash", d.ptr); _exit(0); // crashing is this probe's job; the verdict got out } extern (C) void
void app.onAlarm(int sig) nothrow @nogc
onAlarm
(int
(parameter) int sig
sig
) nothrow @nogc
{ verdict("deadlock", "watchdog_12s_expired"); _exit(0); } // AppKit's main-thread violations usually surface as NSExceptions → capture the // exact assert text before abort() turns it into SIGABRT. extern (C) void
void app.onUncaught(void* exception)
onUncaught
(void*
(parameter) void* exception
exception
)
{
(unresolved type) NSException
NSException
_error_ e
e
= cast(
(unresolved type) NSException
NSException
) exception;
instr("uncaught_exception", "name=%s reason=%s", e !is null ? e.
e.name
name
().
e.name().UTF8String
UTF8String
() : "null",
e !is null ? e.
e.reason
reason
().
e.reason().UTF8String
UTF8String
() : "null");
__gshared char[256]
_error_ d
d
;
snprintf(d.ptr, d.length, "nsexception:%s", e !is null ? e.
e.name
name
().
e.name().UTF8String
UTF8String
() : "unknown");
verdict("crash", d.ptr); _exit(0); } void
void app.installHandlers()
installHandlers
()
{ signal(SIGSEGV, &onFatalSignal); signal(SIGBUS, &onFatalSignal); signal(SIGILL, &onFatalSignal); signal(SIGABRT, &onFatalSignal); signal(SIGTRAP, &onFatalSignal); signal(SIGALRM, &onAlarm); NSSetUncaughtExceptionHandler(cast(
(unresolved type) NSUncaughtExceptionHandler
NSUncaughtExceptionHandler
) &onUncaught);
alarm(12); } // --- Run-loop helpers ---------------------------------------------------------------- void
void app.stopApp()
stopApp
()
{ g_app.
g_app.stop
stop
(null);
(unresolved type) NSEvent
NSEvent
_error_ ev
ev
= NSEvent.
NSEvent.otherEventWithType
otherEventWithType
(NSEventTypeApplicationDefined,
NSPoint(0, 0), 0, 0, 0, null, 0, 0, 0); g_app.
g_app.postEvent
postEvent
(ev, true);
} // Pump the main-thread event queue manually for ~ms milliseconds. void
void app.pumpFor(int ms)
pumpFor
(int
(parameter) int ms
ms
)
{
(unresolved type) NSString
NSString
_error_ mode
mode
= nsstr("kCFRunLoopDefaultMode");
foreach (
(parameter) i
i
; 0 .. ms / 10)
{ for (;;) {
(unresolved type) NSEvent
NSEvent
_error_ e
e
= g_app.
g_app.nextEventMatchingMask
nextEventMatchingMask
(ulong.max, NSDate.
NSDate.distantPast
distantPast
(),
mode, true); if (e is null) break; if (e.
e.type
type
() == NSEventTypeApplicationDefined && e.
e.data1
data1
() == 42)
instr("event", "kind=worker_posted_event_received main_thread=%d data1=%ld", pthread_main_np(), e.
e.data1
data1
());
g_app.
g_app.sendEvent
sendEvent
(e);
} usleep(10_000); } } void
void app.createWindow(const(char)* who)
createWindow
(const(char)*
(parameter) const(char)* who
who
)
{ instr("step", "name=NSWindow_init thread=%s main_thread=%d", who, pthread_main_np()); g_win = PlainWindow.
PlainWindow.alloc
alloc
().
PlainWindow.alloc().initWithContentRect
initWithContentRect
(
NSRect(NSPoint(120, 120), NSSize(320, 240)), NSWindowStyleMaskTitled, NSBackingStoreBuffered, false); g_win.
g_win.setTitle
setTitle
(nsstr("wsi-f17"));
g_win.
g_win.setReleasedWhenClosed
setReleasedWhenClosed
(false);
g_view = ProbeView.
ProbeView.alloc
alloc
().
ProbeView.alloc().initWithFrame
initWithFrame
(NSRect(NSPoint(0, 0), NSSize(320, 240)));
g_win.
g_win.setContentView
setContentView
(g_view);
g_win.
g_win.makeKeyAndOrderFront
makeKeyAndOrderFront
(null);
instr("step", "name=window_created thread=%s win_num=%ld", who, g_win.
g_win.windowNumber
windowNumber
());
} // --- Probe 1: NSWindow on a second thread; main pumps -------------------------------- extern (C) void*
void* app.probe1Worker(void* arg)
probe1Worker
(void*
(parameter) void* arg
arg
)
{ auto
_error_ pool
pool
= autoreleasepool_push();
createWindow("worker"); autoreleasepool_pop(pool); g_workerDone = true; return null; } void
void app.probe1()
probe1
()
{ void*
_error_ th
th
;
pthread_create(&th, null, &probe1Worker, null); pumpFor(2500); // events pumped on main while the worker violates the rule pthread_join(th, null); if (g_win !is null) g_win.
g_win.orderOut
orderOut
(null);
char*
_error_ d
d
= g_detail.ptr;
snprintf(d, g_detail.length, "window_created_off_main=%d win=%ld no_assert_no_crash", g_workerDone ? 1 : 0, g_win !is null ? g_win.
g_win.windowNumber
windowNumber
() : -1);
verdict(g_workerDone ? "silent" : "error", d); } // --- Probe 2: [NSApp run] on main; worker creates the window after run starts -------- extern (C) void*
void* app.probe2Worker(void* arg)
probe2Worker
(void*
(parameter) void* arg
arg
)
{ auto
_error_ pool
pool
= autoreleasepool_push();
createWindow("worker_after_run"); autoreleasepool_pop(pool); g_workerDone = true; return null; } void
void app.probe2()
probe2
()
{ g_marshal = Marshal.
Marshal.alloc
alloc
().
Marshal.alloc().init
init
();
NSTimer.
NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(0.3, g_marshal, SEL.register("tick:"), null, true);
instr("step", "name=NSApp_run"); g_app.
g_app.run
run
(); // ticks drive the script (onTick)
if (g_win !is null) g_win.
g_win.orderOut
orderOut
(null);
char*
_error_ d
d
= g_detail.ptr;
snprintf(d, g_detail.length, "run_loop_alive=1 window_created_on_worker_during_run=%d draws=%d", g_workerDone ? 1 : 0, g_draws); verdict(g_workerDone ? "silent" : "error", d); } // --- Probe 3: the sanctioned pattern -------------------------------------------------- extern (C) void
void app.dispatchedToMain(void* ctx)
dispatchedToMain
(void*
(parameter) void* ctx
ctx
) // runs on the main queue
{ g_dispatchOnMain = pthread_main_np(); instr("marshal", "route=dispatch_async_main_queue main_thread=%d", g_dispatchOnMain); maybeFinishProbe3(); } void
void app.maybeFinishProbe3()
maybeFinishProbe3
()
{ if (g_probe != 3 || g_perfSelOnMain < 0 || g_dispatchOnMain < 0) return; char*
_error_ d
d
= g_detail.ptr;
snprintf(d, g_detail.length, "performSelectorOnMainThread_on_main=%d dispatch_async_on_main=%d", g_perfSelOnMain, g_dispatchOnMain); verdict(g_perfSelOnMain == 1 && g_dispatchOnMain == 1 ? "ok" : "error", d); stopApp(); } extern (C) void*
void* app.probe3Worker(void* arg)
probe3Worker
(void*
(parameter) void* arg
arg
)
{ // "Work" off-main, then marshal the UI-facing part to the main thread. ulong
_error_ sum
sum
;
foreach (
(parameter) i
i
; 0 .. 1_000_000)
sum += i; instr("step", "name=worker_work_done sum=%llu main_thread=%d", sum, pthread_main_np()); g_marshal.
g_marshal.performSelectorOnMainThread
performSelectorOnMainThread
(SEL.register("report:"), null, false);
dispatch_async_f(cast(void*) &_dispatch_main_q, null, &dispatchedToMain); return null; } void
void app.probe3()
probe3
()
{ g_marshal = Marshal.
Marshal.alloc
alloc
().
Marshal.alloc().init
init
();
void*
_error_ th
th
;
pthread_create(&th, null, &probe3Worker, null); instr("step", "name=NSApp_run"); g_app.
g_app.run
run
(); // maybeFinishProbe3 stops it
pthread_join(th, null); } // --- Probe 4: render from a second thread --------------------------------------------- extern (C) void
void app.marshaledSetNeedsDisplay(void* ctx)
marshaledSetNeedsDisplay
(void*
(parameter) void* ctx
ctx
)
{ instr("render", "route=marshaled_setNeedsDisplay main_thread=%d", pthread_main_np()); g_view.
g_view.setNeedsDisplay
setNeedsDisplay
(true);
} extern (C) void*
void* app.probe4Worker(void* arg)
probe4Worker
(void*
(parameter) void* arg
arg
)
{ auto
_error_ pool
pool
= autoreleasepool_push();
// (a) The sanctioned render loop: CPU work on the worker, dirty-mark on main. g_fill = 0.9; instr("render", "route=worker_buffer_fill fill=0.9 main_thread=%d", pthread_main_np()); dispatch_async_f(cast(void*) &_dispatch_main_q, null, &marshaledSetNeedsDisplay); usleep(600_000); immutable
_error_ drawsAfterMarshal
drawsAfterMarshal
= g_draws;
// (b1) DIRECT cross-thread setNeedsDisplay: (docs: not thread-safe). g_fill = 0.5; instr("render", "route=direct_setNeedsDisplay_from_worker main_thread=%d", pthread_main_np()); g_view.
g_view.setNeedsDisplay
setNeedsDisplay
(true);
usleep(600_000); // (b2) DIRECT lockFocus + CGContext drawing from the worker. instr("render", "route=direct_lockFocusIfCanDraw_from_worker main_thread=%d", pthread_main_np()); immutable
_error_ locked
locked
= g_view.
g_view.lockFocusIfCanDraw
lockFocusIfCanDraw
();
instr("render", "lockFocusIfCanDraw=%d", locked ? 1 : 0); if (locked) { void*
_error_ ctx
ctx
= NSGraphicsContext.
NSGraphicsContext.currentContext
currentContext
().
NSGraphicsContext.currentContext().CGContext
CGContext
();
CGContextSetRGBFillColor(ctx, 1, 0, 0, 1); CGContextFillRect(ctx, NSRect(NSPoint(0, 0), NSSize(64, 64))); g_view.
g_view.unlockFocus
unlockFocus
();
instr("render", "direct_cgcontext_draw=done from_worker=1"); } autoreleasepool_pop(pool); char*
_error_ d
d
= g_detail.ptr;
snprintf(d, g_detail.length, "marshaled_draws=%d direct_setNeedsDisplay_survived=1 lockFocusIfCanDraw=%d total_draws=%d", drawsAfterMarshal, locked ? 1 : 0, g_draws); g_workerDone = true; return null; } void
void app.probe4()
probe4
()
{ createWindow("main"); g_marshal = Marshal.
Marshal.alloc
alloc
().
Marshal.alloc().init
init
();
NSTimer.
NSTimer.scheduledTimerWithTimeInterval
scheduledTimerWithTimeInterval
(0.3, g_marshal, SEL.register("tick:"), null, true);
void*
_error_ th
th
;
pthread_create(&th, null, &probe4Worker, null); instr("step", "name=NSApp_run"); g_app.
g_app.run
run
(); // onTick stops once the worker is done
pthread_join(th, null); g_win.
g_win.orderOut
orderOut
(null);
verdict("silent", g_detail.ptr); } // --- Probe 5: NSPasteboard + NSEvent APIs from a worker ------------------------------- extern (C) void*
void* app.probe5Worker(void* arg)
probe5Worker
(void*
(parameter) void* arg
arg
)
{ auto
_error_ pool
pool
= autoreleasepool_push();
auto
_error_ pb
pb
= NSPasteboard.
NSPasteboard.generalPasteboard
generalPasteboard
();
immutable
_error_ cc
cc
= pb.
pb.clearContents
clearContents
();
immutable
_error_ ok
ok
= pb.
pb.setString
setString
(nsstr("f17-worker-thread"), nsstr("public.utf8-plain-text"));
(unresolved type) NSString
NSString
_error_ back
back
= pb.
pb.stringForType
stringForType
(nsstr("public.utf8-plain-text"));
instr("step", "name=pasteboard_from_worker main_thread=%d change_count=%ld set_ok=%d readback=%s", pthread_main_np(), cc, ok ? 1 : 0, back !is null ? back.
back.UTF8String
UTF8String
() : "nil");
(unresolved type) NSEvent
NSEvent
_error_ ev
ev
= NSEvent.
NSEvent.otherEventWithType
otherEventWithType
(NSEventTypeApplicationDefined,
NSPoint(0, 0), 0, 0, 0, null, 7, 42, 0); g_app.
g_app.postEvent
postEvent
(ev, false); // postEvent: from a non-main thread
instr("step", "name=postEvent_from_worker main_thread=%d", pthread_main_np()); char*
_error_ d
d
= g_detail.ptr;
snprintf(d, g_detail.length, "pasteboard_set_ok=%d readback_ok=%d postEvent_from_worker=accepted", ok ? 1 : 0, back !is null && strncmp(back.
back.UTF8String
UTF8String
(), "f17-worker-thread", 17) == 0 ? 1 : 0);
autoreleasepool_pop(pool); g_workerDone = true; return null; } void
void app.probe5()
probe5
()
{ void*
_error_ th
th
;
pthread_create(&th, null, &probe5Worker, null); pumpFor(1500); // main pumps; does the worker's posted event arrive here? pthread_join(th, null); verdict(g_workerDone ? "ok" : "error", g_detail.ptr); } // --- Tick script (probes 2 and 4) ------------------------------------------------------ void
void app.onTick()
onTick
()
{ ++g_ticks; if (g_probe == 2) { if (g_ticks == 1) { instr("step", "name=spawn_worker_inside_run tick=%d", g_ticks); void*
_error_ th
th
;
pthread_create(&th, null, &probe2Worker, null); } if (g_ticks >= 6) stopApp(); } else if (g_probe == 4) { if (g_workerDone || g_ticks >= 20) stopApp(); } } // --- Probe driver / parent ----------------------------------------------------------- int
int app.runProbe(int n)
runProbe
(int
(parameter) int n
n
)
{ g_probe = n; installHandlers(); instr("probe_start", "n=%d main_thread=%d", n, pthread_main_np()); if (CGMainDisplayID() == 0) { printf("SKIP: no macOS window server (CGMainDisplayID == 0)\n"); return 0; } logSessionLockState(); auto
_error_ pool
pool
= autoreleasepool_push();
g_app = NSApplication.
NSApplication.sharedApplication
sharedApplication
();
g_app.
g_app.setActivationPolicy
setActivationPolicy
(NSApplicationActivationPolicyRegular);
switch (n) { case 1: probe1(); break; case 2: probe2(); break; case 3: probe3(); break; case 4: probe4(); break; case 5: probe5(); break; default: verdict("error", "unknown_probe"); break; } autoreleasepool_pop(pool); return 0; } // Parent: fork+exec each probe twice (the spec's nondeterminism rule); a crashed // child can never poison the next, and the parent reports every exit status. int
int app.runAll(const(char)* self)
runAll
(const(char)*
(parameter) const(char)* self
self
)
{ foreach (
(parameter) n
n
; 1 .. 6)
{ foreach (
(parameter) run
run
; 1 .. 3)
{ char[32]
_error_ argbuf
argbuf
;
snprintf(argbuf.ptr, argbuf.length, "--probe=%d", n); const(char)*[3]
_error_ argv
argv
= [self, argbuf.ptr, null];
immutable
_error_ pid
pid
= fork();
if (pid == 0) { execv(self, argv.ptr); _exit(127); } int
_error_ status
status
;
waitpid(pid, &status, 0); immutable
_error_ exited
exited
= (status & 0x7f) == 0;
instr("probe_run", "n=%d run=%d exit_normal=%d code=%d term_signal=%d", n, run, exited ? 1 : 0, exited ? (status >> 8) & 0xff : -1, exited ? 0 : status & 0x7f); } } instr("all_probes_done", "runs=10"); return 0; } int
int D main(string[] args)
main
(
(alias) object.string = string
string
[]
(parameter) string[] args
args
)
{ instrInit("APPKIT_F17"); if (args.length > 1 && args[1].length > 8 && args[1][0 .. 8] == "--probe=") return runProbe(atoi(args[1].ptr + 8)); instr("init_start", "mode=all_probes_forked_twice"); if (CGMainDisplayID() == 0) { printf("SKIP: no macOS window server (CGMainDisplayID == 0)\n"); return 0; } char[1024]
_error_ self
self
;
snprintf(self.ptr, self.length, "%s", args[0].ptr); return runAll(self.ptr); }