This section discusses common problems that students ran into over and over again (even after having been warned about them).
What is happening: The pages (in user space) holding the arguments to the system calls are being paged out before the system call routines copy the contents of those pages into local variables. For example, Exec needs the name of the binary file to run. Routine machine::ReadMem does indeed invoke Translate to perform the translation, and if the target page is not present in physical memory, generates a page fault (e.g., by invoking RaiseException). However, ReadMem does not retry the fetch operation; instead, it returns FALSE indicating that the operation failed. Thus, the first byte the user attempts to fetch will not be retrieved. If Nachos immediately restarts the operation, the page will now be present in memory (the probability is very high anyway). If ReadMem is called from a loop that fetches one character at a time, skipping the first character will likely cause the wrong thing to happen (it is frequently NULL in practice, terminating the string). The same problem occurs with WriteMem. and can occur with any system calls that take pointers as arguments.
One shortcut that students want to make is to simply retry the ReadMem operation when it fails. That is, they assume that the only reason ReadMem fails is because the target page was paged out. If the pointer is invalid (e.g., outside of the process's address space), however, retrying the operation results in the same failure. Indeed, Nachos goes into an infinite loop at this point.
What is happening: Dangling references. Although this is a standard C programming problem, students repeatedly forgot to allocate space for strings. For example, as part of the Exec system call, it is useful for debugging purposes to store the name of the file with the address space. This requires allocating space to hold the string and copying that file name into that newly allocated space. In contrast, students often simply set a pointer to the file name argument passed to the routine that implements Exec. However, when that routine returns, the Exec system call completes, and the space that held the file name gets deallocated. Chance are good that the next system call to be executed will reuse the same space, placing different data in its contents.