I'm working on multitasking.
I have such a simple tasks(task01, task02, task03)
I add these tasks to the list of threads that are executed in turn.
Since "return" cannot normally complete the task, I have the scheduler_thread_exit_current function(), it works as needed and successfully completes the task.
In cases where this function is not present, "return" passes control to the wrong place and a #UD or #GP exception occurs.
I want the process to be forcibly terminated if any of these exceptions occur.
But I found that my process table gets corrupted after calling an exception.
Describe how the exception works.
When exceptions occur, an assembly function(general_protection_fault) is called that calls the handler in C and passes parameters to it.
Control is then passed to the main handler(general_protection_fault_exception).
This is where the error is detected.
The logs show that when the first thread ends(id = 1)(voluntary termination), the process table looks like this.
Then control is passed to thread 3 (id = 3), there is no voluntary termination and #GP occurs, which just prints the process table, the address of the [2] element (thread 3) is incorrect, and its id is displayed incorrectly.
I don't know what could have damaged it.
I also tried browsing memory using qemu. Here's what he showed me(tested on task02 (thread 2), that's why #UD appears here):
You can see that by the time task02() completes, the address data is correct.

But as soon as control is passed to the handler in C(I couldn't debug the assembly header, my debugger can't do it there), the data in this cell damaged.

I believe there are errors in the assembler handler, but I don't see anything problematic there.
What might be the problem?
I would appreciate your help!