<html><head><style>body{font-family:Helvetica,Arial;font-size:13px}</style></head><body style="word-wrap:break-word"><div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto">On March 25, 2017 at 9:56:03 PM, Gwynne Raskind (<a href="mailto:gwynne@darkrainfall.org">gwynne@darkrainfall.org</a>) wrote:</div> <blockquote type="cite" class="clean_bq"><span><div style="word-wrap:break-word" class=""><div></div><div>
<title></title>
<br class="">
<div>
<blockquote type="cite" class="">
<div class="">On Mar 25, 2017, at 19:27, Elijah Johnson via
swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div id="bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;margin:0px" class=""><br class="">
On March 25, 2017 at 7:15:59 PM, Elijah Johnson (<a href="mailto:ejrx7753@gmail.com" class="">ejrx7753@gmail.com</a>)
wrote:</div>
<div style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">
<blockquote type="cite" class="clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<div style="word-wrap:break-word" class="">
<div class=""><span class=""><br class="Apple-interchange-newline">
<br class=""></span>
<div id="bloop_sign_1490476884916890112" class="bloop_sign"></div>
<span class=""><br class=""></span>
<p class="airmail_on"><span class="">On March 25, 2017 at 10:24:23
AM, Elijah Johnson (<a href="mailto:ejrx7753@gmail.com" class="">ejrx7753@gmail.com</a>) wrote:</span></p>
<div class="">
<blockquote type="cite" class="clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<div style="word-wrap:break-word" class="">
<div class=""><span class=""><span class=""><br class="Apple-interchange-newline">
<br class=""></span></span>
<div id="bloop_sign_1490451116213062912" class="bloop_sign"></div>
<span class=""><br class=""></span>
<p class="airmail_on"><span class="">On March 23, 2017 at 12:01:48
PM, Joe Groff (<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>) wrote:</span></p>
<div class="">
<blockquote type="cite" class="clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<div class="" style="word-wrap:break-word">
<div class="">
<div class="">
<blockquote type="cite" class="">
<div class=""><span class=""><span class=""><br class="Apple-interchange-newline">
On Mar 22, 2017, at 7:25 PM, Elijah Johnson <<a href="mailto:ejrx7753@gmail.com" class="">ejrx7753@gmail.com</a>>
wrote:</span></span></div>
<span class=""><br class="Apple-interchange-newline"></span>
<div class="">
<div id="bloop_customfont" class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;margin:0px">
<span class="">On March 22, 2017 at 8:41:25 PM, Joe Groff (<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>)
wrote:</span></div>
<div class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<blockquote type="cite" class="clean_bq" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<div class="">
<div class=""></div>
<div class=""><span class=""><span class=""><br class="">
> On Mar 22, 2017, at 4:07 PM, Elijah Johnson <<a href="mailto:ejrx7753@gmail.com" class="">ejrx7753@gmail.com</a>>
wrote:<span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
> Hi,<span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
> Note that this thread has branched off a bit, so my latest
proposal and the “head” of this thread can be found at<span class="Apple-converted-space"> </span><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html</a><span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
> Can you give an example of this corruption which would be
exploitable in a web server context? An example where, having
caught the force-unwrap or other precondition fatalError, that the
web server would face more danger from continued execution that it
would loose by crashing?<span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
> The optional has been triggered, the request has been stopped,
and incoming requests are going to a new process, but there are a
few threads open still finishing what they were doing - I’d like to
see a good example of the danger caused by a real “inconsistency”.
Lets assume also that all objects shared between threads are Swift
objects and not “UnsafePointers”, which is a very fair assumtion
for a web server. Java even allows native access and they don’t
even crash there.<span class="Apple-converted-space"> </span><br class="">
<br class="">
When considering security threats, we have to take the presence of
an exploit as given until we prove otherwise. A precondition
failure indicates a logic error somewhere in the program, and while
safe Swift abstractions are intended not to lead to memory unsafety
in the face of precondition failures, there's plenty of relatively
young, unsafe code below the hood in the implementations of those
abstractions, written by humans who make mistakes. Whatever lurking
security bugs there may be, they're more likely to be exploitable
if you're already in a situation where assumptions have been
violated.<span class="Apple-converted-space"> </span><br class="">
<br class="">
> I’m sorry, but I completely fail to grasp the danger as being
> crashing.<span class="Apple-converted-space"> </span><br class="">
<br class="">
Crashing is inconvenient. The user may have to retry their request
or relaunch their app. Security breaches or data corruption are
disasters that can have unbounded impact and cost—you can't
undisclose sensitive data.<span class="Apple-converted-space"> </span><br class="">
<br class="">
> I’d be interested to know who these web server developers (ex.
Kitura, Vapor) are targeting without any form of crash handling and
if they read these threads. It really limits the pool of developers
more so than on apps because a single crash on the app ie
equivelant to a failed request, not a crashed web server. I realize
you are not competing with Java, but I do not see yet the
compelling reason for no crash handling.<span class="Apple-converted-space"> </span><br class="">
><span class="Apple-converted-space"> </span><br class="">
> The “actors” with thread pool and proccesses is one idea, but
I think these servers are aiming also for speed and scaleability -
don’t know if they would accept this model. I know that it does get
used, and do work for a company that uses it on their backend (just
plain Java, not sep. processes). Their front-end probably runs like
a pre-fork server, but Java is so stable that there is simply no
need for that.<span class="Apple-converted-space"> </span><br class="">
<br class="">
You can use processes for fault isolation today, and that will have
some cost. At Swift's current maturity level, that's really
probably the only responsible isolation strategy. The goal of
"actors" would be to get most of the benefits of processes through
language-level isolation without paying the full cost of
processes.<span class="Apple-converted-space"> </span><br class="">
<br class="">
-Joe</span></span></div>
</div>
</blockquote>
</div>
<p class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
<br class=""></p>
<p class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
I have no personal objection to actors or processes or anything
else. I would just emphasize that the webservers in existence for
Swift (and quite well funded) are right now on a “crash the whole
thing” model AFAIK. I don’t know if they will be able to get by
with catching all the precondition failures in testing - maybe they
will - maybe not, but I see people either wisely turning down Swift
for web development or getting their first crash as a “zero-day”
system down event where some guy has to ssh in and actually start
the server back up.</p>
</div>
</blockquote>
I haven't worked directly with server people that much personally,
but on the opportunities when I have been able to talk to people
working in this space, it sounds like they definitely want
something better.<br class="">
<blockquote type="cite" class="">
<div class="">
<p class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
But whatever the fix is, or nothing, they (developers of Perfect,
Kitura, Vapor, etc) will have to like it and implement it. If
they’re not interested, I’m not starting a development company to
compete.</p>
</div>
</blockquote>
<div class="">I don't see a problem with people developing
frameworks to the best of the platform's ability today and refining
their approach as new capabilities get developed.</div>
<blockquote type="cite" class="">
<div class="">
<p class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
And also the development time is so short on my idea that you
basically just have to approve it and the development time for it
is hours not months or years. Just add a fatalError function
override and any c developer could have it done in minutes like
this guy <a href="https://github.com/ankurp/unsafe-swift" class="">https://github.com/ankurp/unsafe-swift</a> (not
endorsing the post, just showing evidence that setjmp and longjmp
work fine with swift).</p>
<div class="" style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px">
</div>
</div>
</blockquote>
</div>
setjmp and longjmp do *not* work well with Swift since they need
compiler support to implement their semantics, and since Swift does
not provide this support, setjmp-ing from Swift is undefined
behavior. Empirical evidence that small examples appear to work is
not a good way of evaluating UB, since any changes to Swift or LLVM
optimizations may break it. Ease of implementation is also not a
good criterion for designing things. *Supporting* a trap hook is
not easy; it still has serious language semantics and runtime
design issues, and may limit our ability to do something better.
<div class=""><br class=""></div>
<div class="">-Joe</div>
</div>
</div>
</blockquote>
</div>
<p class=""><br class=""></p>
<p class="">Yeah, I suppose. Sounds like it is still about 2-3
years off.</p>
</div>
</div>
</blockquote>
</div>
<p class=""><br class=""></p>
<p class="">But…. what happens when a shared or shared sub-process
trips? If something about the process was shared, then it will end
up tripping every other process except some master process which
will re-generate them.</p>
<p class="">Concerning longjmp, it is possible to call from Swift
into C, and then from C into Swift (not in the example, but in
general). Therefore, assuming that the execution state of the C
function is still on the stack at the moment that the exception
trips, the jump won’t necessarily involve the Swift runtime or
compiler at all, so far as I can see, aside from leaked memory.
Granted I don’t know that much about the runtime, but an example
might be useful.</p>
<p class="">The linked example is was done inline, so a bit
different than I was thinking.</p>
<p class="">BTW, not sure why no one mentioned it, but apparently
the whole idea proposed is already possible without any proposal
actually needed. A bit too complex for me and dangerous looking,
but heres a nice post with it already done.</p>
<p class=""><a href="https://www.cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html#setting-up-a-mach-exception-handler" class="">https://www.cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html#setting-up-a-mach-exception-handler</a></p>
</div>
</div>
</blockquote>
</div>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">How about going half way on a proposal for a “fatalError”
callback, which would take a “c” function (or be accessible only
from c) to prevent recursion. ie. if the handler was in Swift the
callback would then be liable to induce another fatalError.</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">The purpose of which would be to log the fatal error
string to a file.</p>
<div style="font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;margin:0px;font-size:11px;line-height:normal;font-family:Menlo" class=""><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)" class="">int</span><span style="font-variant-ligatures:no-common-ligatures" class=""><span class="Apple-converted-space"> </span>fatalErrorCallback(</span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)" class="">char</span><span style="font-variant-ligatures:no-common-ligatures" class="">*
message,<span class="Apple-converted-space"> </span></span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(186,45,162)" class="">char</span><span style="font-variant-ligatures:no-common-ligatures" class="">*
stacktrace);</span></div>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Any other usages would be unsupported and something to
discuss in the dev channel (no bearing on the ABI or compiler
design, only the reverse). If it returns “0” then Swift omits its
own std output, but in either case it exits.</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">One can see easily from the error printout that Swift is
running its own callback, even in Swift:</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><br class=""></p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">fatal error: unexpectedly found nil while unwrapping an
Optional value</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Current stack trace:</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">0 TestJmp1
0x0000000104b11410 swift_reportError + 132</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">1 TestJmp1
0x0000000104b2e7c0 _swift_stdlib_reportFatalError + 61</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">2 TestJmp1
0x000000010489c550 specialized specialized
StaticString.withUTF8Buffer<A>
((UnsafeBufferPointer<UInt8>) -> A) -> A + 355</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">3 TestJmp1
0x0000000104a9e7f0 partial apply for
(_fatalErrorMessage(StaticString, StaticString, StaticString, UInt,
flags : UInt32) -> Never).(closure #2) + 109</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">4 TestJmp1
0x000000010489c550 specialized specialized
StaticString.withUTF8Buffer<A>
((UnsafeBufferPointer<UInt8>) -> A) -> A + 355</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">5 TestJmp1
0x0000000104a59170 specialized _fatalErrorMessage(StaticString,
StaticString, StaticString, UInt, flags : UInt32) -> Never +
96</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">6 TestJmp1
0x00000001047f87f0 (closure #1) + 221</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">7 TestJmp1
0x00000001047f8a30 @objc (closure #1) + 9</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">8 TestJmp1
0x00000001047f8ae0 runCode + 49</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">9 TestJmp1
0x00000001047f8700 main + 87</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">10 libdyld.dylib
0x00007fffe1deb254 start +
1</p>
<p style="font-family:Helvetica,Arial;font-size:13px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="">Illegal instruction: 4</p>
</div>
</blockquote>
<div>If all you can do is log an alternative to what Swift would
output anyway, what's the use case? And certainly permitting more
things to happen in that callback falls under the same caveats as
an in-process crash reporter - compromised context, uncertain data
state, very few safe operations.</div>
<div><br class=""></div>
<div>-- Gwynne Raskind</div>
<div><br class=""></div>
</div>
</div></div></span></blockquote><br><div>By “in process crash reporter” are you referring to the link above (<a href="https://www.cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html#setting-up-a-mach-exception-handler">https://www.cocoawithlove.com/blog/2016/02/02/partial-functions-part-two-catching-precondition-failures.html#setting-up-a-mach-exception-handler</a>)?</div><div><br></div><div>The difference between that, and using longjmp (defering the judgment of what the side effects are to another channel than evolution) would be that one has specificly caught a "fatalError" and not something else. It contains the error message and stack trace easily avaiable, and is not confusable with another "EXE bad instruction”.</div><div><br></div><div>As to the supported use case, it would be to write the stack trace to a file and then exit, or similar operation using isolated C functions. We can see that the current handler allocates memory and runs instructions on them in the same thread before it exits. The supported use would be to do the same, ideally in C which does not compile fatalError instructions (causing recursion), but uses its own signals to crash.</div><div><br></div><div>Not every process wants to pipe its output and error somewhere besides the console or /dev/null. I’m not aware exactly what currently exists for crash reporting on Swift, so maybe this is redundant also.</div><div><br></div><div>Then, certain developers can discuss the runtime impact of unwiding the stack via a c longjmp, and weigh its impact in their particular use case, but not in the forum of swift evolution.</div><div><br></div><div>Lets see, in Errors.cpp, you have a function called reportNow (called by swift_fatalError) with this line:</div><div><br></div><div><span class="pl-c1" style="box-sizing:border-box;color:rgb(0,134,179);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">asl_log</span><span style="color:rgb(36,41,46);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">(</span><span class="pl-c1" style="box-sizing:border-box;color:rgb(0,134,179);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">nullptr</span><span style="color:rgb(36,41,46);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">, </span><span class="pl-c1" style="box-sizing:border-box;color:rgb(0,134,179);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">nullptr</span><span style="color:rgb(36,41,46);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">, ASL_LEVEL_ERR, </span><span class="pl-s" style="box-sizing:border-box;color:rgb(24,54,145);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre"><span class="pl-pds" style="box-sizing:border-box">"</span>%s<span class="pl-pds" style="box-sizing:border-box">"</span></span><span style="color:rgb(36,41,46);font-family:SFMono-Regular,Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;font-variant-ligatures:normal;white-space:pre">, message);</span></div><div><br></div><div>but it is only for Apple platforms. So you will need a user-defined callback for linux platforms, in case their linux distro has a system log they want to write to. Or whatever they want to do with logging.</div></body></html>