1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:37:46 +00:00

Fix some bugs in execve() and make sh use it for process launching.

Interrupting children of sh now always works with ^C :^)
This commit is contained in:
Andreas Kling 2018-11-03 02:04:36 +01:00
parent 202bdb553c
commit 20fb1fc377
4 changed files with 24 additions and 24 deletions

View file

@ -152,8 +152,6 @@ auto MemoryManager::ensurePTE(PageDirectory* page_directory, LinearAddress laddr
laddr.get(), laddr.get(),
page_table); page_table);
#endif #endif
if (page_table.get() == 0x71d000)
ASSERT(page_directory == m_kernel_page_directory);
page_directory->physical_addresses[page_directory_index] = page_table; page_directory->physical_addresses[page_directory_index] = page_table;
pde.setPageTableBase(page_table.get()); pde.setPageTableBase(page_table.get());
pde.setUserAllowed(true); pde.setUserAllowed(true);

View file

@ -346,8 +346,7 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en
new_page_directory = reinterpret_cast<PageDirectory*>(kmalloc_page_aligned(sizeof(PageDirectory))); new_page_directory = reinterpret_cast<PageDirectory*>(kmalloc_page_aligned(sizeof(PageDirectory)));
MM.populate_page_directory(*new_page_directory); MM.populate_page_directory(*new_page_directory);
m_page_directory = new_page_directory; m_page_directory = new_page_directory;
MM.enter_process_paging_scope(*this);
ProcessPagingScope pagingScope(*this);
space.hookableAlloc = [&] (const String& name, size_t size) { space.hookableAlloc = [&] (const String& name, size_t size) {
if (!size) if (!size)
return (void*)nullptr; return (void*)nullptr;
@ -357,11 +356,12 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en
}; };
bool success = space.loadELF(move(elfData)); bool success = space.loadELF(move(elfData));
if (!success) { if (!success) {
MM.release_page_directory(*new_page_directory);
m_page_directory = old_page_directory; m_page_directory = old_page_directory;
MM.enter_process_paging_scope(*this);
MM.release_page_directory(*new_page_directory);
m_regions = move(old_regions); m_regions = move(old_regions);
m_subregions = move(old_subregions); m_subregions = move(old_subregions);
kprintf("Failure loading ELF %s\n", path.characters()); kprintf("sys$execve: Failure loading %s\n", path.characters());
return -ENOEXEC; return -ENOEXEC;
} }
@ -378,8 +378,9 @@ int Process::sys$execve(const char* filename, const char** argv, const char** en
entry_eip = (dword)space.symbolPtr("_start"); entry_eip = (dword)space.symbolPtr("_start");
if (!entry_eip) { if (!entry_eip) {
MM.release_page_directory(*new_page_directory);
m_page_directory = old_page_directory; m_page_directory = old_page_directory;
MM.enter_process_paging_scope(*this);
MM.release_page_directory(*new_page_directory);
m_regions = move(old_regions); m_regions = move(old_regions);
m_subregions = move(old_subregions); m_subregions = move(old_subregions);
return -ENOEXEC; return -ENOEXEC;

View file

@ -5,7 +5,6 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
setpgid(0, 0);
if (argc != 2) { if (argc != 2) {
printf("usage: cat <file>\n"); printf("usage: cat <file>\n");
return 1; return 1;

View file

@ -142,16 +142,15 @@ static bool handle_builtin(int argc, const char** argv, int& retval)
return false; return false;
} }
static int try_spawn(const char* path, const char** argv) static int try_exec(const char* path, const char** argv)
{ {
int ret = spawn(path, argv); int ret = execve(path, argv, nullptr);
if (ret >= 0) assert(ret < 0);
return ret;
const char* search_path = "/bin"; const char* search_path = "/bin";
char pathbuf[128]; char pathbuf[128];
sprintf(pathbuf, "%s/%s", search_path, argv[0]); sprintf(pathbuf, "%s/%s", search_path, argv[0]);
ret = spawn(pathbuf, argv); ret = execve(pathbuf, argv, nullptr);
if (ret == -1) if (ret == -1)
return -1; return -1;
return ret; return ret;
@ -181,21 +180,24 @@ static int runcmd(char* cmd)
return 0; return 0;
} }
int ret = try_spawn(argv[0], argv); pid_t child = fork();
if (ret < 0) { if (!child) {
printf("spawn failed: %s (%s)\n", cmd, strerror(errno)); setpgid(0, 0);
return 1; tcsetpgrp(0, getpid());
int ret = try_exec(argv[0], argv);
if (ret < 0) {
printf("exec failed: %s (%s)\n", cmd, strerror(errno));
exit(1);
}
// We should never get here!
assert(false);
} }
// FIXME: This is racy, since spawn has already started the new process.
// Once I have fork()+exec(), pgrp setup can be done in the child before exec()ing.
tcsetpgrp(0, ret);
// FIXME: waitpid should give us the spawned process's exit status
int wstatus = 0; int wstatus = 0;
waitpid(ret, &wstatus, 0); waitpid(child, &wstatus, 0);
// FIXME: Racy as mentioned above. Rework once we have fork()+exec(). // FIXME: Should I really have to tcsetpgrp() after my child has exited?
// Is the terminal controlling pgrp really still the PGID of the dead process?
tcsetpgrp(0, getpid()); tcsetpgrp(0, getpid());
if (WIFEXITED(wstatus)) { if (WIFEXITED(wstatus)) {