Skip to content

mp_execute_bytecode causes exception while getting GIL #7606

@bhcuong2008

Description

@bhcuong2008

Hi,

I have made a custom build MPY 1.16 ESP32 port, esp-idf v3.3.5, no SPIRAM, to integrate into Arduino. I use the whole core 1 for MPY thread. On core 1, there are only 2 extra system threads: IDLE1, ipc1. I have created another MPY thread in C code, MPThreadCMesh, besides MPY main thread.

My detail issue is here. The issue is still there.
peterhinch/micropython-async#60

However, my new issue is different, related to running sync code, so I report here.
Yesterday I had found new update for esp32 port here: #5344

This update is good. I see better performance. Before the update, I got some random exceptions, especially BREAK like my async issue. With the new update, I ran my test 3 times, got the same exception. It will help to find out the cause, rather than random exception found before.

Here is my actual test on my final application. The test is incrementing variable _cntButton up to element 0 of array N, N[0], then reset to zero. Here its value is 10. I do sleep with 50ms. I make this test to make more computations on MPY. The test failed after from 30 minutes to several hours (2, 3). I run this code inside REPL. While this code run in REPL, thread MPThreadCMesh doing only delay using mp_hal_delay_ms(1), and checking FreeRTOS queue to get new message from C side. "cmo20.o" is a class, inherit from dict, class DObj(dict).

def test_push(period):
   cmo20 = cmo(20)
   while 1:
      try:
         cmo20.o._cntButton = 0 if not hasattr(cmo20.o, '_cntButton') or cmo20.o._cntButton >= N[0] else cmo20.o._cntButton + 1
         parse_in_post_demo(cmo20, 1);
         time.sleep_ms(period)
      except Exception as e:
         print(str(e))

def parse_in_post_demo(cmobj, args):
   is_send = 0
   if args is None:
      if cmobj.o.contact:
         if hasattr(cmobj.o, '_cntButton'):
            cmobj.o._cntButton = cmobj.o._cntButton + 1 if cmobj.o._cntButton < N[0] else 0
         else:
            cmobj.o._cntButton = 0
         is_send = 1
   elif args == 1:
      is_send = 1
   
   if is_send:
      x = {"apitype": "ext", "command": "cmesh/set", "group":10, "data": {"quiet":1, "data": [[20, 0, {'_cntButton': cmobj.o._cntButton}]]}}
      _cconn(x)


N[0] = 10
test_push(50)

The exception here, luckily it's not BREAK instr:

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x401d4d66  PS      : 0x00060030  A0      : 0x8008aa74  A1      : 0x3ffd70d0  
A2      : 0x00000000  A3      : 0x00000001  A4      : 0x3ffc985c  A5      : 0x00000001  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x801d3b92  A9      : 0x3ffccef0  
A10     : 0x00000001  A11     : 0x3f42b654  A12     : 0x3ffc9c38  A13     : 0x00000044  
A14     : 0x3ffcd020  A15     : 0x3ffccf80  SAR     : 0x0000001e  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x401d4d66:0x3ffd70d0 0x4008aa71:0x3ffd70f0 0x401d951d:0x3ffd7130 0x401d93d1:0x3ffd7150 0x400fa4e8:0x3ffd7180 0x401d97cc:0x3ffd71a0 0x401d9441:0x3ffd7240 0x4008ac62:0x3ffd7260

0x401d5062: mp_execute_bytecode at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/py/vm.c line 1436
0x4008aa71: xQueueGenericReceive at /home/cuongbh/esp32/arduino_build/lib_335/esp-idf/components/freertos/queue.c line 1592
0x401d9819: mp_thread_mutex_lock at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 230
0x401d96cd: mp_hal_delay_ms at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mphalport.c line 231
0x400fa704: MPThreadCMesh(size_t, size_t, mp_obj_t const*) at C:\Users\cuongbh\AppData\Local\Temp\arduino_build_557899\sketch\mpy.cpp line 405
0x401d9ac8: app_thread_entry at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 327
0x401d973d: freertos_entry at /home/cuongbh/esp32/arduino_build/lib_335/components/micropython/esp32/mpthreadport.c line 151
0x4008ac62: vPortTaskWrapper at /home/cuongbh/esp32/arduino_build/lib_335/esp-idf/components/freertos/port.c line 143

The exception occurs while getting GIL. I google portYIELD_WITHIN_API, often related to interrupt. I dont understand that there is any relation between portYIELD_WITHIN_API and its effect on executing mp_execute_bytecode. LoadProhibited due to access "->type" reading at address 0x00000000 (specified by EXCVADDR). I guess that.

mphalport.c line 231: MP_THREAD_GIL_ENTER();
mpthreadport.c line 230: return pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0);
queue.c line 1592: portYIELD_WITHIN_API();
vm.c line 1436: if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {

If using simple dict like this, it's always running (above 7 hours). I guess that it's due to simpler code execution, not face corner situtation.

x = {}
def test_exception2(period):   
   while 1:
      try:
         x['_cntButton'] = 0 if '_cntButton' not in x or x['_cntButton'] >= N[0] else x['_cntButton'] + 1

         y = {"apitype": "ext", "command": "cmesh/set", "group":10, "data": {"quiet":1, "data": [[20, 0, {'_cntButton': x['_cntButton']}]]}}  
         _cconn(y)       

         time.sleep_ms(period)
      except Exception as e:
         print(str(e))

Thank you,
Cuong.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions