[Solved]Catch exception raised in C in python

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
BramPeeters
Posts: 54
Joined: Wed Jan 31, 2018 3:10 pm

[Solved]Catch exception raised in C in python

Post by BramPeeters » Tue Oct 02, 2018 2:40 pm

Hi.

I just read an (old) thread about this topic (viewtopic.php?f=2&t=178) which seems to indicate that it is possible to 'catch' an 'exception' in a python try-except block that is raised in C.
However i am not able to reproduce that nor do I understand how to get it working.

The original thread use an MP_RAISE macro around nlr_raise, which as the original thread points out just is a setjmp/longjmp (to where nlr_push was done).
In my case this is in execute_from_string (based on the demo code), so it is outside of the mp_call_function_0 which i used to start the python code.

Code: Select all

     if (nlr_push(&nlr) == 0)
    {
        qstr src_name = MP_QSTR_;
        mp_lexer_t *lex = mp_lexer_new_from_str_len( src_name, str, strlen(str), false);
        mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
        mp_obj_t module_fun = mp_compile(&pt, src_name, MP_EMIT_OPT_NONE, false);
        mp_call_function_0(module_fun);
        nlr_pop();
        return 0;
    } else {
      //exception handling code, C level
    ...
    }
I don't see how with I can change this mechanism to end up in try block at python level similar to the dhtest.py example from the original thread. Was this possible in older versions but not anymore ? Should i use something else than the nlr_raise based functions (mp_raise_msg & co) ? Did I misunderstand the original thread ?

Thanks
Bram
Last edited by BramPeeters on Tue Oct 02, 2018 3:34 pm, edited 1 time in total.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Catch exception raised in C in python

Post by stijn » Tue Oct 02, 2018 2:56 pm

Does nlr_raise not work for you somehow? It's all that's needed.. As in, under normal circumstances if you are in a Python script in a try/except block and call a function which is implemented in C and the latter one in turn uses nlr_raise, that exception will make it to the except block. It's how all of the source code works. But it's not really clear to me what you are trying exactly, can you show some code?

BramPeeters
Posts: 54
Joined: Wed Jan 31, 2018 3:10 pm

Re: Catch exception raised in C in python

Post by BramPeeters » Tue Oct 02, 2018 3:34 pm

You describe exactly what I was trying to do and after rechecking it in fact it works perfect, thank you!
How does it work under the hood, does try 'try' instruction (temporary) replace the target jump address ?

The reason it did not seem to work before is because I was still using an old .py script without a try except block so it jumped to the initial C level nlr_push(&nlr) point. And it was still the old script because i copy the scripts over to my target using USB drivers from stm which get an award for being horrible (amongst many others, busy waiting at interrupt level, why not) and every once and a while just do not copy a file even though you think it was successful. Only after your comment that it should work I read back the file and i noticed it....my bad.

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Catch exception raised in C in python

Post by jickster » Tue Oct 02, 2018 4:49 pm

BramPeeters wrote:
Tue Oct 02, 2018 3:34 pm
How does it work under the hood, does try 'try' instruction (temporary) replace the target jump address ?
Clarify this question.

stijn
Posts: 735
Joined: Thu Apr 24, 2014 9:13 am

Re: Catch exception raised in C in python

Post by stijn » Wed Oct 03, 2018 8:51 am

BramPeeters wrote:
Tue Oct 02, 2018 3:34 pm
How does it work under the hood, does try 'try' instruction (temporary) replace the target jump address ?
Would be possible theoretically I think (might get messy for nested try blocks though) but it's done in a different way, see use of PUSH_EXC_BLOCK and the exception_handler label in mp_execute_bytecode in vm.c: the main vm loop just sets some flags to indicate whether currently in a try block and if so stores the exception on the stack then continues execution (e.g. doing something with the exception in the except block), whereas when there was no try block execution stops there and mp_execute_bytecode returns MP_VM_RETURN_EXCEPTION to indicate that, which is handled further.

BramPeeters
Posts: 54
Joined: Wed Jan 31, 2018 3:10 pm

Re: [Solved]Catch exception raised in C in python

Post by BramPeeters » Sun Oct 07, 2018 4:38 pm

Ok, thanks for the pointers/explanation !

Post Reply