mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-02 07:30:58 +00:00
noux: reflect -no memory- case during process setup
Instead of just red messages in the log and a hanging caller, the issuer may respond to it - e.g. a noux bash shell will show an error and is afterwards still usable. Fixes #1778
This commit is contained in:
parent
c7df65e1da
commit
e9525f49fd
@ -266,7 +266,8 @@ namespace Noux {
|
|||||||
enum Clock_Id { CLOCK_ID_SECOND };
|
enum Clock_Id { CLOCK_ID_SECOND };
|
||||||
|
|
||||||
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = Vfs::Directory_service::NUM_GENERAL_ERRORS };
|
enum Fcntl_error { FCNTL_ERR_CMD_INVALID = Vfs::Directory_service::NUM_GENERAL_ERRORS };
|
||||||
enum Execve_error { EXECVE_NONEXISTENT = Vfs::Directory_service::NUM_GENERAL_ERRORS };
|
enum Execve_error { EXECVE_NONEXISTENT = Vfs::Directory_service::NUM_GENERAL_ERRORS, EXECVE_NOMEM };
|
||||||
|
enum Fork_error { FORK_NOMEM = Vfs::Directory_service::NUM_GENERAL_ERRORS };
|
||||||
enum Select_error { SELECT_ERR_INTERRUPT };
|
enum Select_error { SELECT_ERR_INTERRUPT };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -339,6 +340,7 @@ namespace Noux {
|
|||||||
Utimes_error utimes;
|
Utimes_error utimes;
|
||||||
Wait4_error wait4;
|
Wait4_error wait4;
|
||||||
Kill_error kill;
|
Kill_error kill;
|
||||||
|
Fork_error fork;
|
||||||
|
|
||||||
} error;
|
} error;
|
||||||
|
|
||||||
|
@ -549,6 +549,11 @@ extern "C" pid_t fork(void)
|
|||||||
|
|
||||||
if (!noux_syscall(Noux::Session::SYSCALL_FORK)) {
|
if (!noux_syscall(Noux::Session::SYSCALL_FORK)) {
|
||||||
PERR("fork error %d", sysio()->error.general);
|
PERR("fork error %d", sysio()->error.general);
|
||||||
|
switch (sysio()->error.fork) {
|
||||||
|
case Noux::Sysio::FORK_NOMEM: errno = ENOMEM; break;
|
||||||
|
default: errno = EAGAIN;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sysio()->fork_out.pid;
|
return sysio()->fork_out.pid;
|
||||||
@ -1008,6 +1013,7 @@ namespace {
|
|||||||
PWRN("exec syscall failed for path \"%s\"", filename);
|
PWRN("exec syscall failed for path \"%s\"", filename);
|
||||||
switch (sysio()->error.execve) {
|
switch (sysio()->error.execve) {
|
||||||
case Noux::Sysio::EXECVE_NONEXISTENT: errno = ENOENT; break;
|
case Noux::Sysio::EXECVE_NONEXISTENT: errno = ENOENT; break;
|
||||||
|
case Noux::Sysio::EXECVE_NOMEM: errno = ENOMEM; break;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -296,9 +296,20 @@ namespace Noux {
|
|||||||
|
|
||||||
bool _syscall_net(Syscall sc);
|
bool _syscall_net(Syscall sc);
|
||||||
|
|
||||||
|
void _destruct() {
|
||||||
|
|
||||||
|
_sig_rec->dissolve(&_destruct_dispatcher);
|
||||||
|
|
||||||
|
_entrypoint.dissolve(this);
|
||||||
|
|
||||||
|
if (is_init_process(this))
|
||||||
|
init_process_exited(_child_policy.exit_value());
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Binary_does_not_exist : Exception { };
|
struct Binary_does_not_exist : Exception { };
|
||||||
|
struct Insufficient_memory : Exception { };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
@ -312,6 +323,8 @@ namespace Noux {
|
|||||||
* specified name could not be
|
* specified name could not be
|
||||||
* looked up at the virtual file
|
* looked up at the virtual file
|
||||||
* system
|
* system
|
||||||
|
* \throw Insufficent_memory if the child could not be started by
|
||||||
|
* the parent
|
||||||
*/
|
*/
|
||||||
Child(char const *binary_name,
|
Child(char const *binary_name,
|
||||||
Parent_exit *parent_exit,
|
Parent_exit *parent_exit,
|
||||||
@ -379,19 +392,17 @@ namespace Noux {
|
|||||||
|
|
||||||
if (!forked && !_elf._binary_ds.valid()) {
|
if (!forked && !_elf._binary_ds.valid()) {
|
||||||
PERR("Lookup of executable \"%s\" failed", binary_name);
|
PERR("Lookup of executable \"%s\" failed", binary_name);
|
||||||
|
|
||||||
|
_destruct();
|
||||||
throw Binary_does_not_exist();
|
throw Binary_does_not_exist();
|
||||||
}
|
}
|
||||||
|
if (!_child.main_thread_cap().valid()) {
|
||||||
|
_destruct();
|
||||||
|
throw Insufficient_memory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~Child()
|
~Child() { _destruct(); }
|
||||||
{
|
|
||||||
_sig_rec->dissolve(&_destruct_dispatcher);
|
|
||||||
|
|
||||||
_entrypoint.dissolve(this);
|
|
||||||
|
|
||||||
if (is_init_process(this))
|
|
||||||
init_process_exited(_child_policy.exit_value());
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() { _entrypoint.activate(); }
|
void start() { _entrypoint.activate(); }
|
||||||
|
|
||||||
|
@ -387,6 +387,8 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
|||||||
}
|
}
|
||||||
catch (Child::Binary_does_not_exist) {
|
catch (Child::Binary_does_not_exist) {
|
||||||
_sysio->error.execve = Sysio::EXECVE_NONEXISTENT; }
|
_sysio->error.execve = Sysio::EXECVE_NONEXISTENT; }
|
||||||
|
catch (Child::Insufficient_memory) {
|
||||||
|
_sysio->error.execve = Sysio::EXECVE_NOMEM; }
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -583,28 +585,34 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
|||||||
Genode::addr_t parent_cap_addr = _sysio->fork_in.parent_cap_addr;
|
Genode::addr_t parent_cap_addr = _sysio->fork_in.parent_cap_addr;
|
||||||
|
|
||||||
int const new_pid = pid_allocator()->alloc();
|
int const new_pid = pid_allocator()->alloc();
|
||||||
|
Child * child = nullptr;
|
||||||
|
|
||||||
/*
|
try {
|
||||||
* XXX To ease debugging, it would be useful to generate a
|
/*
|
||||||
* unique name that includes the PID instead of just
|
* XXX To ease debugging, it would be useful to generate a
|
||||||
* reusing the name of the parent.
|
* unique name that includes the PID instead of just
|
||||||
*/
|
* reusing the name of the parent.
|
||||||
Child *child = new Child(_child_policy.name(),
|
*/
|
||||||
this,
|
child = new Child(_child_policy.name(),
|
||||||
_kill_broadcaster,
|
this,
|
||||||
*this,
|
_kill_broadcaster,
|
||||||
new_pid,
|
*this,
|
||||||
_sig_rec,
|
new_pid,
|
||||||
root_dir(),
|
_sig_rec,
|
||||||
_args,
|
root_dir(),
|
||||||
_env.env(),
|
_args,
|
||||||
_cap_session,
|
_env.env(),
|
||||||
_parent_services,
|
_cap_session,
|
||||||
_resources.ep,
|
_parent_services,
|
||||||
true,
|
_resources.ep,
|
||||||
env()->heap(),
|
true,
|
||||||
_destruct_queue,
|
env()->heap(),
|
||||||
verbose);
|
_destruct_queue,
|
||||||
|
verbose);
|
||||||
|
} catch (Child::Insufficient_memory) {
|
||||||
|
_sysio->error.fork = Sysio::FORK_NOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Family_member::insert(child);
|
Family_member::insert(child);
|
||||||
|
|
||||||
@ -1078,7 +1086,24 @@ Genode::Lock &Noux::signal_lock()
|
|||||||
|
|
||||||
|
|
||||||
void *operator new (Genode::size_t size) {
|
void *operator new (Genode::size_t size) {
|
||||||
return Genode::env()->heap()->alloc(size); }
|
void * ptr = Genode::env()->heap()->alloc(size);
|
||||||
|
if (!ptr)
|
||||||
|
return ptr;
|
||||||
|
|
||||||
|
Genode::memset(ptr, 0, size);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void operator delete (void * ptr)
|
||||||
|
{
|
||||||
|
if (Genode::env()->heap()->need_size_for_free()) {
|
||||||
|
PWRN("leaking memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::env()->heap()->free(ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename FILE_SYSTEM>
|
template <typename FILE_SYSTEM>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user