Return of problematic values in gen_* functions error tuples

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Return of problematic values in gen_* functions error tuples

Lutz Behnke
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.
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}.

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}


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.

mfg lutz

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

phone: +49 40 42875-8156    mailto:[hidden email]
fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
Berliner Tor 7, 20099 Hamburg, Germany

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Return of problematic values in gen_* functions error tuples

Dmitry Klionsky-2
 >> Why are the offending values not returned as part of the tuple when
signaling an error in virtually all of the stdlib function?

The values might be huge.



On 09/19/2018 02:08 PM, 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.
> 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}.
>
> 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}
>
>
> 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.
>
> mfg lutz
>

--
BR,
Dmitry

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Return of problematic values in gen_* functions error tuples

Raimo Niskanen-11
In reply to this post by Lutz Behnke
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:[hidden email]
> fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
> Berliner Tor 7, 20099 Hamburg, Germany
>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Return of problematic values in gen_* functions error tuples

Lutz Behnke
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:[hidden email]
>> fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
>> Berliner Tor 7, 20099 Hamburg, Germany
>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> 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:[hidden email]
fax  : +49 40 2803770       http://users.informatik.haw-hamburg.de/~sage
Berliner Tor 7, 20099 Hamburg, Germany
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Return of problematic values in gen_* functions error tuples

Raimo Niskanen-11
On Wed, Sep 19, 2018 at 05:10:51PM +0200, Lutz Behnke wrote:
> Hi Raimo,
:
>
> 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.... :-)

Glad to be of assistance! ;-)

>
> Thx
>
> mfg lutz
>
>

--

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions