[swift-evolution] Swift null safety questions

Elijah Johnson ejrx7753 at gmail.com
Wed Mar 22 18:12:04 CDT 2017


TLDR version, I would check with the developers of Swift web servers
(Vapor, Kitura, etc) if this is their actual plan also to re-work their
webserver using actors and processes instead of threads. I’m not writing a
webserver myself, so that is what it should come down to. Right now, if you
unwrap an optional, it crashes their entire server. It just seems
thoughtless to me.


On March 22, 2017 at 7:07:04 PM, Elijah Johnson (ejrx7753 at gmail.com) wrote:

Hi,

Note that this thread has branched off a bit, so my latest proposal and the
“head” of this thread can be found at
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20170320/034189.html



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?

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. I’m sorry, but I completely fail to grasp the
danger as being > crashing.

As for “hard to debug” errors, providing a stack trace and logging it,
stopping the one request that caused it, is sufficient for debugging a
production environment.



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.

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.



On March 22, 2017 at 1:03:42 PM, Joe Groff (jgroff at apple.com) wrote:


On Mar 6, 2017, at 4:20 PM, Elijah Johnson via swift-evolution <
swift-evolution at swift.org> wrote:

Hi,

I’ve been recently considering Swift on the server-side, and there came up
the question, “what happens when a null optional is forcibly unwrapped?”
and the answer was clearly that not only would the request crash, but the
entire server would also crash, since the server itself is/would be also
written in Swift.

I think that this highlights serveral weaknesses in Swift’s “null safety”
attempts. The first is that there needs to be a way to isolate blocks of
code so that a “null pointer exception” does not crash the system. I think
it is fair to say, in the language of Java, that these are really “runtime
exceptions” and for some reason are being treated as segmentation faults
would be in C/C++. In my opinion, the existence of these things has the
ability to bring Swift down below Java and closer to an unamanged language.
Not really sure why it would ever be desireable, but in terms of
server-side programming, it is definitely a serious issue.

Secondly, Swift’s “null safety” is really completely undermined by these
“force-unwrap” errors. I agree with the usage of new language features like
guard, optional binding, etc to remove a null value, but I see this
force-unwrap as extremely pervasive for a lot of reasons:

1. When porting code from a C style language to Swift, force-unwrap is
needed to make the code work without refractoring.
2. XCode itself reccomends this operator and when it is used to satisfy a
requirement, then it can be left in the code
3. Some styles of coding just can’t work without force-unwrap.

I don’t think the logic of making the consequences extreme for making a
mistake are a rational for making better coders. In fact, I personally see
the “force-unwrap” operator having very great potential usage as a
deliberate assertion exception - the programmer demands that a certain
value be non-null for execution to continue, only there should be a proper
scope and context where these exceptions can propogate to. On debug modes,
one might want it to pause on the line, but for other uses, it should be
caught IMO - on regular code by the user, and inside dispatch blocks by the
queue itself. For a multithreaded app or server to exit, the user should
have to explicitly write exit(0), isn’t this the goal of a managed
language? Maybe in some cases, Apple will want the program to crash, but if
Swift is given an audience not just with Apple hardware, then it should
have more flexibility IMO.


The long-term vision here is to have some form of finer-grained fault
isolation ("actors" being the buzzword for that we tend to throw around).
As others noted, using `!` is intended to indicate that it is *impossible*
for a value to be nil at a certain point, and that the programmers screwed
up if the value is nil at that point. The only safe thing to do in a
situation the programmers didn't plan for is stop execution; anything else
is just going to lead to harder-to-debug, potentially-exploitable
inconsistencies further removed from the original problem. With actors, it
could become possible for that crash to only take down an isolated
subprogram, and give a supervisor subprogram an opportunity to gracefully
wind down the process—on clients, this might mean saving application state
so that the app can be cleanly restarted, and on the server, this might
mean closing the process's accept socket but still letting existing
requests complete before restarting the potentially-compromised process.
There's still a tradeoff here from a defense-in-depth standpoint, since any
requests running in the same process have the potential to corrupt each
other's state. Swift's crash-early design hopes to minimize the opportunity
for corruption to leak.

-Joe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170322/49c5dc70/attachment.html>


More information about the swift-evolution mailing list