Kernel: Tidy up Process::try_create_user_process()

This function is currently only ever used to create the init process
(SystemServer). It had a few idiosyncratic things about it that this
patch cleans up:

- Errors were returned in an int& out-param.
- It had a path for non-0 process PIDs which was never taken.
This commit is contained in:
Andreas Kling 2021-09-04 22:36:06 +02:00
parent ba1a6ca971
commit 3b995c6d01
Notes: sideshowbarker 2024-07-18 04:44:57 +09:00
3 changed files with 19 additions and 28 deletions

View File

@ -143,32 +143,26 @@ void Process::register_new(Process& process)
});
}
RefPtr<Process> Process::create_user_process(RefPtr<Thread>& first_thread, const String& path, UserID uid, GroupID gid, ProcessID parent_pid, int& error, Vector<String>&& arguments, Vector<String>&& environment, TTY* tty)
KResultOr<NonnullRefPtr<Process>> Process::try_create_user_process(RefPtr<Thread>& first_thread, String const& path, UserID uid, GroupID gid, Vector<String> arguments, Vector<String> environment, TTY* tty)
{
auto parts = path.split('/');
if (arguments.is_empty()) {
arguments.append(parts.last());
}
RefPtr<Custody> cwd;
if (auto parent = Process::from_pid(parent_pid))
cwd = parent->m_cwd;
if (!cwd)
cwd = VirtualFileSystem::the().root_custody();
auto process = Process::try_create(first_thread, parts.take_last(), uid, gid, parent_pid, false, move(cwd), nullptr, tty);
auto process = Process::try_create(first_thread, parts.take_last(), uid, gid, ProcessID(0), false, VirtualFileSystem::the().root_custody(), nullptr, tty);
if (!process || !first_thread)
return {};
return ENOMEM;
if (!process->m_fds.try_resize(process->m_fds.max_open())) {
first_thread = nullptr;
return {};
return ENOMEM;
}
auto& device_to_use_as_tty = tty ? (CharacterDevice&)*tty : NullDevice::the();
auto description_or_error = device_to_use_as_tty.open(O_RDWR);
if (description_or_error.is_error()) {
error = description_or_error.error().error();
return {};
}
if (description_or_error.is_error())
return description_or_error.error();
auto& description = description_or_error.value();
auto setup_description = [&process, &description](int fd) {
@ -179,20 +173,18 @@ RefPtr<Process> Process::create_user_process(RefPtr<Thread>& first_thread, const
setup_description(1);
setup_description(2);
error = process->exec(path, move(arguments), move(environment)).error();
if (error != 0) {
dbgln("Failed to exec {}: {}", path, error);
if (auto result = process->exec(path, move(arguments), move(environment)); result.is_error()) {
dbgln("Failed to exec {}: {}", path, result);
first_thread = nullptr;
return {};
return result;
}
register_new(*process);
error = 0;
// NOTE: All user processes have a leaked ref on them. It's balanced by Thread::WaitBlockerSet::finalize().
(void)process.leak_ref();
process->ref();
return process;
return process.release_nonnull();
}
RefPtr<Process> Process::create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data, u32 affinity, RegisterProcess do_register)

View File

@ -179,7 +179,7 @@ public:
}
static RefPtr<Process> create_kernel_process(RefPtr<Thread>& first_thread, String&& name, void (*entry)(void*), void* entry_data = nullptr, u32 affinity = THREAD_AFFINITY_DEFAULT, RegisterProcess do_register = RegisterProcess::Yes);
static RefPtr<Process> create_user_process(RefPtr<Thread>& first_thread, const String& path, UserID, GroupID, ProcessID ppid, int& error, Vector<String>&& arguments = Vector<String>(), Vector<String>&& environment = Vector<String>(), TTY* = nullptr);
static KResultOr<NonnullRefPtr<Process>> try_create_user_process(RefPtr<Thread>& first_thread, String const& path, UserID, GroupID, Vector<String> arguments, Vector<String> environment, TTY*);
static void register_new(Process&);
bool unref() const;

View File

@ -336,18 +336,17 @@ void init_stage2(void*)
// NOTE: Everything in the .ksyms section becomes inaccessible after this point.
MM.unmap_ksyms_after_init();
int error;
// FIXME: It would be nicer to set the mode from userspace.
// FIXME: It would be smarter to not hardcode that the first tty is the only graphical one
ConsoleManagement::the().first_tty()->set_graphical(GraphicsManagement::the().framebuffer_devices_exist());
RefPtr<Thread> thread;
auto userspace_init = kernel_command_line().userspace_init();
auto init_args = kernel_command_line().userspace_init_args();
Process::create_user_process(thread, userspace_init, UserID(0), GroupID(0), ProcessID(0), error, move(init_args), {}, tty0);
if (error != 0) {
PANIC("init_stage2: Error spawning SystemServer: {}", error);
}
auto init_or_error = Process::try_create_user_process(thread, userspace_init, UserID(0), GroupID(0), move(init_args), {}, tty0);
if (init_or_error.is_error())
PANIC("init_stage2: Error spawning init process: {}", init_or_error.error());
thread->set_priority(THREAD_PRIORITY_HIGH);
if (boot_profiling) {