Skip to content

sys_process_exec crashes on qemu-2.11.1 #191

@jmazanec15

Description

@jmazanec15

I am trying to create a window manager user program in which a list of programs are passed to the window manager and the window manager forks and execs each of them in their own windows. However, there seems to be a bug in the exec call.

Initially, running this fork and exec program fails:

#include "library/syscalls.h"
#include "library/string.h"

int main()
{
	int pid = process_fork();

	if (pid == 0) {
		printf("hello world, I am the child %d.\n", process_self());
		const char *args[] = { "snake.exe" };
		process_exec("snake.exe", args, 1);
	} else {
		printf("hello world, I am the parent %d.\n", process_self());
		struct process_info info;
		process_wait(&info, -1);
		process_reap(info.pid);
	}

	return 0;
}

It produces the following exception:
image

After doing some debugging, I have found that something goes wrong in the process_switch function. At the end of the sys_process_exec, it calls process_yield, which calls process_switch(PROCESS_STATE_READY). Here is the code for process_switch:

static void process_switch(int newstate)
{
	interrupt_block();

	if(current) {
		if(current->state != PROCESS_STATE_CRADLE) {
			asm("pushl %ebp");
			asm("pushl %edi");
			asm("pushl %esi");
			asm("pushl %edx");
			asm("pushl %ecx");
			asm("pushl %ebx");
			asm("pushl %eax");
		      asm("movl %%esp, %0":"=r"(current->kstack_ptr));
		}

		interrupt_stack_pointer = (void *) INTERRUPT_STACK_TOP;
		current->state = newstate;

		if(newstate == PROCESS_STATE_READY) {
			list_push_tail(&ready_list, &current->node);
		}
		if(newstate == PROCESS_STATE_GRAVE) {
			list_push_tail(&grave_list, &current->node);
		}
	}

	current = 0;

	while(1) {
		current = (struct process *) list_pop_head(&ready_list);
		if(current)
			break;

		interrupt_unblock();
		interrupt_wait();
		interrupt_block();
	}
	current->state = PROCESS_STATE_RUNNING;
	interrupt_stack_pointer = current->kstack_top;

	asm("movl %0, %%cr3"::"r"(current->pagetable));
	asm("movl %0, %%esp"::"r"(current->kstack_ptr));

	asm("popl %eax");
	asm("popl %ebx");
	asm("popl %ecx");
	asm("popl %edx");
	asm("popl %esi");
	asm("popl %edi");
	asm("popl %ebp");

	interrupt_unblock();
}

I have found that the program works by adding a dumby for loop before the while loop as a delay:

	for (int i = 0; i < 100000; ++i)
	{
		continue;
	}

	while(1) {

While this obviously is not a solution, I think it might indicate that there is some kind of race condition going on.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions