[erlang-questions] Return of problematic values in gen_* functions error tuples

Lutz Behnke lutz.behnke@REDACTED
Wed Sep 19 17:10:51 CEST 2018


Hi Raimo,

you are right. I misread the code in gen_statem.erl:1314. I thought the 
actual result is thrown away (by using '_ ->....'), but it is available 
in Result. So that has helped me find the spot to continue debugging my 
own code (which should not throw/return badarg AFAIK).

Ok, I understand the argument of the parameter being in the stack trace. 
But I seem to run in to situations where crossing the process boundary 
will invalidate the stack trace.

Ah! I have just understood that the whole problem was of my very own 
creation (and has been for some time, due to a misunderstanding of the 
proper use of the throw primitive.)

Thank you for shining a light at the sordid underbelly of my code. I 
will now proceed to duplicate methods and concepts from the way 
gen_statem handles errors.... :-)

Thx

mfg lutz


Am 19.09.2018 um 14:03 schrieb Raimo Niskanen:
> On Wed, Sep 19, 2018 at 01:08:27PM +0200, Lutz Behnke wrote:
>> Hi there,
>>
>> I have question I have been wondering about for some time, but which is
>> bugging me right now:
>>
>> 	Why are the offending values not returned as part of the tuple
>>           when signaling an error in virtually all of the stdlib function?
>>
>> Example: The gen_statem:parse_event_result/8 will terminate the state
>> machine with {bad_return_from_state_function,badargs}, but not include
>> the offending value.
> 
> Bad example on your part, I think.
> 
> That particular exception is of class 'error' with reason
> {bad_return_from_state_function,Result} where Result is the term
> that the state function returned that is: the offending value.
> 
> So if the state machine terminates with that reason there is
> a state function that has returned 'badargs' instead of
> an event_handler_result(StateType).
> 
> Which state function that returned 'badargs' is unfortunately lost since
> the code has returned from the function, but the current state is recorded
> in the error report, which indirectly points out the offending state
> function.
> 
>> IMO it would help a lot in determining the cause of the fault.
>> This is similar in a wide range of functions in all the gen_* modules as
>> well as ets functions. I think I remember some other cases throughout
>> the stdlib, but don't have any ready examples.
>> Sometimes the functions just throw a fault with {error, badargs}.
> 
> That would be "the function just throws an exception of class 'error'
> with reason 'badarg'", just for the record.
> 
>>
>> Why not include the bad argument?
>>    e.g. {bad_return_from_state_function, {badargs, TheBadTerm}}
>>     from gen_statem:parse_event_result/8
>> or
>>    ets:lookup/3 could return {bardarg, Key}
> 
> That would be ets:lookup_element/3, and yes, it throws an exception of
> class 'error' with reason just 'badarg'.
> 
> That is a standard reason, and introducing {badarg,Info} would probably
> surprise lots of debug tools.
> 
> If you get the stack trace from that exception you will see that
> the arguments are in the first element, so therefore it redundant
> to have any part of the arguments in the exception reason.
> 
> gen_statem throws a more specific reason that does not use the well known
> 'badarg' reason, partly because in your example it is not an argument to a
> function that is bad - it is a return value, and partly to introduce a
> more describing keyword for which it is not unexpected to have
> supplementary info.
> 
>>
>>
>> I know that it will break the API to a certain extend, but will patches
>> to change this be considered for inclusion in the mainly sources? I have
>> looked at the gen_statem code and am considering a fork to help me debug.
> 
> Changing return values of API functions is not backwards compatible, so
> that would most probably not be considered.
> 
> Changing an exception reason is less sensitive, but changing the toplevel
> term in this case 'badarg' into a tuple is rather likely to break code that
> catches and inspects the reason.  If the documentation says that the reason
> is something like {broad_reason,Description} the Description could
> probably be changed since code that follows the documentation could only
> match for {broad_reason,_} and would not break.
> 
> In short we can change what is not documented.
> (with lots of exceptions, unfortunately)
> 
> Improvement suggestions of gen_statem's exception reasons are welcome, but
> I have already put some effort into making them useful, so I am a bit
> surprised that you bring gen_statem up as the first module to improve...
> And I do not agree with the example you gave - have you got better examples
> or can you please clarify?
> 
> Best Regards
> / Raimo Niskanen
> 
> 
>>
>> mfg lutz
>>
>> -- 
>> Lutz Behnke
>> Hochschule für Angewandte Wissenschaften Hamburg,
>> Labor für Allgemeine Informatik,
>>
>> phone: +49 40 42875-8156    mailto:lutz.behnke@REDACTED
>> fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
>> Berliner Tor 7, 20099 Hamburg, Germany
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
> 

-- 
Lutz Behnke
Hochschule für Angewandte Wissenschaften Hamburg,
Labor für Allgemeine Informatik,

phone: +49 40 42875-8156    mailto:lutz.behnke@REDACTED
fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
Berliner Tor 7, 20099 Hamburg, Germany



More information about the erlang-questions mailing list