When you finished the process system call (e.g.,
execv) and test your
system call by executing some user program, you'll probably find that the
console input behavior is messed up.
For example, when you executing user shell from OS161 kernel menu, and then
/bin/true from the shell, you may see this
OS/161 kernel [? for menu]: s Operation took 0.000285120 seconds OS/161 kernel [? for menu]: (program name unknown): Timing enabled. OS/161$ /bin/true (program name unknown): bntu: No such file or directory (program name unknown): subprocess time: 0.063300440 seconds Exit 1
In this case, the shell program only receive the input "bnut" instead of your
To find out why, we need to dig into how kernel menu (
works a little bit. When you hit "s" in the kernel menu. What happens?
cmd_dispatchwill look up the
common_progwith the shell path argument
common_progwill first create a child thread with the start function
cmd_progthread, then return
In the child thread,
cmd_progthreadwill try to run the actual program (in our case, the shell)
Note that the shell program is run in a separate child thread, and the parent thread (i.e., the menu thread) will continue to run after he "forked" the child thread.
So now there are actually two thread that want to read console input, which leads to race condition. This is why the shell program receive corrupted input: the menu thread eaten some of the inputs!
To solve this problem, we need to let the menu thread wait for the child
thread to complete, then return. So what we need to do is in
need to do a
waitpid operation after we call
thread_fork. And at the end of
cmd_progthread, we need to explicitly call
exit with proper exit code in
case the user program doesn't do this.
Also note that
exit are in fact user land system call, and we can
not directly call them in kernel, so you may need to make some "shortcuts" in
your system call implementation to let the kernel be able to call