[swift-evolution] Preconditions aborting process in server scenarios [was: Throws? and throws!]

Rien Rien at Balancingrock.nl
Wed Jan 18 02:04:22 CST 2017


> On 18 Jan 2017, at 08:54, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Jan 17, 2017, at 7:13 PM, Dave Abrahams <dabrahams at apple.com> wrote:
>> 
>> 
>> on Tue Jan 17 2017, Jonathan Hull <jhull-AT-gbis.com> wrote:
>> 
>>> Bringing it back towards the initial post, what if there was a
>>> separation from true needs-to-take-down-the-entire-system trapping and
>>> things like out-of-bounds and overflow errors which could stop at
>>> thread/actor bounds (or in some cases even be recovered)?
>>> 
>>> The latter were the ones I was targeting with my proposal.  They live
>>> in this grey area, because honestly, they should be throwing errors if
>>> not for the performance overhead and usability issues.  
>> 
>> I fundamentally disagree with that statement.  There is value in
>> declaring certain program behaviors illegal, and in general for things
>> like out-of-bounds access and overflow no sensible recovery (where
>> “recovery” means something that would allow the program to continue
>> reliably) is possible.  
> 
> I think we do fundamentally disagree.  I know I come from a very different background (Human-Computer Interaction & Human Factors) than most people here, and I am kind of the odd man out, but I have never understood this viewpoint for anything but the most severe cases where the system itself is in danger of being compromised (certainly not for an index out of bounds).  In my mind “fail fast” is great for iterating in development builds, but once you are deploying, the user’s needs should come ahead of the programmer’s.
> 
> Shouldn’t a system be as robust as possible

Yes

> and try to minimize the fallout from any failure point?

That is in direct conflict with the robustness
Once an error is detected that is not handled by the immediate code, it must be assumed that a worst-case scenario happened. And further damage to the user can only be prevent by bringing down the app. Even if that means losing all work in progress.

A compromised system must be prevent from accessing any resources. Once a system is compromised the risk to the user is *much* higher than simply loosing work in progress. He might loose his job, career, etc.

Rien.


>  I don’t consider crashing and losing all of the user’s data minimal.  It used to be that something like dividing by zero took down the entire machine.  Now we mimic that by crashing the application, even though it isn’t strictly necessary.  Wouldn’t it be even better if we only took down the current operation, notified the user about what happened and continue on?
> 
> Swift does a great job of using forcing functions (like optionals) to make some errors impossible, and this is literally the opposite of that. This requires the programmer to remember to add a check that the number is within certain bounds, but there is no reminder for them to do that.  The failure is silent (i.e. there isn’t a ‘!’ or ’try' to mark that it is a possibility), at runtime, under certain conditions and not others.  It is a recipe for bugs which cause a crash for the user.
> 
> If we wanted fool-proof arrays, then the subscript would return an optional, forcing the programmer to think about and deal with the possibility of out-of-bounds failure (that is how we handle dictionary lookups after all).  If I remember correctly, we don’t do that because of performance. Instead we ask the programmer to remember to check against the array count first, just like we used to ask the programmer to remember to check for nil pointers in C++.
> 
> The idea that a programmer can or should be perfect is a lovely fantasy…  My CS teachers always talked about how it would encourage bad programming if there wasn’t punishment for making these types of mistakes.
> 
> I don’t see the value in punishing the user for the programmer’s mistake, and I have rarely seen a case where sensible recovery wouldn’t be possible (given Swift’s error handling).  In most real-world applications, you would just end up cancelling whatever operation was happening, reverting to the state before it, and notifying the user of the problem.  The programming languages which get into trouble are the ones which treat everything as valid, so they just keep barreling on, overwriting data or something like that.  We don’t have that problem though, since we have sensible error handling that can be used to fail an operation and get things back to a previous state (or better yet, avoiding overwriting the state until after the operation has succeeded).  We should aim for robustness, and crashing isn’t robust.
> 
> Please note: I am not saying we allow memory access out of bounds. We are still triggering an error state when these things happen (either returning nil or throwing an error), we’re just not crashing the entire program because of it.
> 
> 
> 
>> 
>>> My solution was to give the compiler a way to know that this was the
>>> desired behavior and optimize the throwing away unless it was
>>> explicitly requested.
>>> 
>>> I guess another option would be to introduce a new concept for this
>>> grey type of error.  Maybe instead of ‘fatalError’ you have something
>>> with a different name saying “this should only take down the current
>>> actor”… and then you add a well defined process for cleanup.
>>> 
>>> I would still really like to see the ability to turn this type of
>>> thing into normal throwing error handling, so maybe something like
>>> ‘fatalThrow’ which takes the same information as ‘throw’, so that it
>>> can be converted to a standard throw by the caller, but otherwise
>>> traps and takes down the actor.  That would make certain types of
>>> algorithms much simpler for me.
>>> 
>>> Thanks,
>>> Jon
>>> 
>>>> On Jan 17, 2017, at 11:49 AM, Dave Abrahams via swift-evolution <swift-evolution at swift.org> wrote:
>>>> 
>>>> 
>>>> on Mon Jan 16 2017, Chris Lattner <swift-evolution at swift.org
>>>> <mailto:swift-evolution at swift.org>> wrote:
>>>> 
>>>>>> On Jan 16, 2017, at 3:57 PM, David Waite via swift-evolution
>>>>> <swift-evolution at swift.org> wrote:
>>>>>> 
>>>>>> My interpretation is that he was advocating a future where a
>>>>>> precondition’s failure killed less than the entire process. Instead,
>>>>>> shut down some smaller portion like a thread, actor, or container
>>>>> 
>>>>>> like .Net's app domains (which for those more familiar with
>>>>>> Javascript could be loosely compared with Web Workers).
>>>>>> 
>>>>>> Today - if you wanted a Swift server where overflowing addition
>>>>>> didn’t interrupt your service for multiple users, you would need to
>>>>>> use something like a pre-fork model (with each request handled by a
>>>>>> separate swift process)
>>>>>> 
>>>>>> That's the difference between CLI and desktop apps where the process
>>>>>> is providing services for a single user, and a server where it may
>>>>>> be providing a service for thousands or millions of users.
>>>>> 
>>>>> Agreed, I’d also really like to see this some day.  It seems like a
>>>>> natural outgrowth of the concurrency model, if it goes the direction
>>>>> of actors.  
>>>>> 
>>>>> If you’re interested, I speculated on this direction in this talk:
>>>>> http://researcher.watson.ibm.com/researcher/files/us-lmandel/lattner.pdf
>>>>> <http://researcher.watson.ibm.com/researcher/files/us-lmandel/lattner.pdf
>>>>> <http://researcher.watson.ibm.com/researcher/files/us-lmandel/lattner.pdf>>
>>>> 
>>>> I totally support the idea of emergency shutown measures
>>>> (e.g. save document for recovery), 
>>>> 
>>>> In general, though, when a precondition is violated, it means your
>>>> program state is compromised in an arbitrarily bad way.  Unfortunately,
>>>> that applies equally across process boundaries as it does across thread
>>>> boundaries, if there's some kind of static guarantee of safety as might
>>>> be provided by actors.  This means you need a way to make decisions
>>>> about which kinds of precondition violations should be considered
>>>> recoverable as long as you're willing to abandon the job, and which
>>>> really do need to be fatal for the whole process... and I don't know if
>>>> anyone's really ever figured that problem out.  It'd be cool if Swift
>>>> could solve it.
>>>> 
>>>> -- 
>>>> -Dave
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> -- 
>> -Dave
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list