pycom / pycom-micropython-sigfox

A fork of MicroPython with the ESP32 port customized to run on Pycom's IoT multi-network modules.
MIT License
196 stars 167 forks source link

WiPy restarts when exiting thread #546

Open x4t-de opened 3 years ago

x4t-de commented 3 years ago

Please include the following information when submitting a bug report:

`import _thread import time

import random

import uos import gc

configTest = {}

def BuildConfig(Config): items = [[0,10],[1,20],[2,5]] layers = len(items) for i in range (0,layers): layerName = "layer{}".format(i) Config[layerName] = {} for j in range(0,items[i][1]): itemName = "item{}ofLayer{}".format(j,i)

Config[layerName][itemName] = random.randrange(100)

        Config[layerName][itemName] = uos.urandom(1)[0]

Config["changeIterations"] = 0

def ChangeConfig(Config): for key in Config: if key != "changeIterations": for item in Config[key]:

Config[key][item] = random.randrange(100)

            Config[key][item] = uos.urandom(1)[0]
            #print("changing item {} of layer {}".format(item,key))

Config["changeIterations"] += 1

variable0 = 0 variable1 = 0 variable2 = 0 variable3 = 0 variable4 = 0 variable5 = 0 variable6 = 0 variable7 = 0 variable8 = 0 variable9 = 0

TEST_THREADFUNCTION = "b" TEST_GCCOLLECT = False

lock = _thread.allocate_lock()

threadList = []

def ThreadFunction(Config, LifeTime, Id): global variable0 global variable1 global variable2 global variable3 global variable4 global variable5 global variable6 global variable7 global variable8 global variable9

with lock:
    threadList[Id] = 1

#create some internal variables that occupy memory
array = [[0 for i in range (0,10)] for j in range (0,10)]

#randomSleepTime = random.randrange(LifeTime * 10 * 3)/(LifeTime*10.0)
randomSleepTime = (uos.urandom(1)[0] / 256.0) * (LifeTime * 3.0)
#print("thread {} random sleep time:{}".format(Id, randomSleepTime))
time.sleep(randomSleepTime)

for i in range (0,100):
    with lock:
        ChangeConfig(Config)

time.sleep(LifeTime)

with lock:
    threadList[Id] = 0

array[0][0] = Id

def ThreadFunctionB(Config, LifeTime, Id): global variable0 global variable1 global variable2 global variable3 global variable4 global variable5 global variable6 global variable7 global variable8 global variable9

with lock:
    threadList[Id] = 1

#create some internal variables that occupy memory
array = [[0 for i in range (0,10)] for j in range (0,10)]

#randomSleepTime = random.randrange(LifeTime * 10 * 3)/(LifeTime*10.0)
randomSleepTime = (uos.urandom(1)[0] / 256.0) * (LifeTime * 3.0)
#print("thread {} random sleep time:{}".format(Id, randomSleepTime))
time.sleep(randomSleepTime)

for i in range (0,100):
    with lock:
        ChangeConfig(Config)

time.sleep(LifeTime)

with lock:
    threadList[Id] = 0

array[0][0] = Id
print("thread {} will now terminate".format(Id))    # this seems to lead to restart

def ThreadCreator(NumberOfThreads, ThreadLifeTime, PrintMemFree = True): global configTest global threadList

threadList = [0 for i in range(0,NumberOfThreads)]

print("creating {} threads with a life time of {} seconds".format(NumberOfThreads, ThreadLifeTime))
for i in range(0,NumberOfThreads):
    if TEST_GCCOLLECT:
        gc.collect()

    memFreeBefore = 0
    if PrintMemFree:
        memFreeBefore = gc.mem_free()

    if TEST_THREADFUNCTION == "a":
        _thread.start_new_thread(ThreadFunction, (configTest, ThreadLifeTime, i))
    elif TEST_THREADFUNCTION == "b":
        _thread.start_new_thread(ThreadFunctionB, (configTest, ThreadLifeTime, i))

    memFreeAfter = 0
    if PrintMemFree:
        memFreeAfter = gc.mem_free()

    print("spawning at {} % (last id {}) - memory (bef/aft/diff): {} \t{} \t{}".format(int((i + 1) * 100 / NumberOfThreads), i, memFreeBefore, memFreeAfter, memFreeBefore - memFreeAfter), end="\r\n")

print()    
time.sleep(1)

print("waiting for threads to finish")
for i in range(0,NumberOfThreads):
    while threadList[i] != 0:
        time.sleep(1)

    print("thread with id = {} has exited".format(i))

print("all threads have exited")

def RunThreadTest(NumberOfThreads, ThreadLifeTime, PrintMemFree = True): BuildConfig(configTest)

print("test config before thread start")
print(configTest)

ThreadCreator(NumberOfThreads,ThreadLifeTime, PrintMemFree)

print("test config after threads finished")
print(configTest)

def RunThreadTestWithRestarts(NumberOfRestarts, NumberOfThreads, ThreadLifeTime, PrintMemFree = True): BuildConfig(configTest) print("test config before thread start") print(configTest)

for i in range(0,NumberOfRestarts):
    print("### restart {} of {}".format(i + 1, NumberOfRestarts))
    ThreadCreator(NumberOfThreads,ThreadLifeTime, PrintMemFree)
    print("test config after threads finished")
    print(configTest)

`

Thank you!

x4t-de commented 3 years ago

Sorry I don't know why the code snippet gets destroyed like that. I also attached the ZIP with the Python file.

peter-pycom commented 3 years ago

I can't reproduce this. I tried for about an hour with different values RunThreadTestWithRestarts(20,1,1) or (20,20,2), (200,1,1), a and b. On a wipy and on a fipy.

Can you reproduce the reboot with just this script or does the reproduction require your confidential code? How quickly can you reproduce this?