diff --git a/ports/src/noux/child.h b/ports/src/noux/child.h index f3946d2ea..8a0399def 100644 --- a/ports/src/noux/child.h +++ b/ports/src/noux/child.h @@ -254,6 +254,8 @@ namespace Noux { public: + struct Binary_does_not_exist : Exception { }; + /** * Constructor * @@ -261,6 +263,11 @@ namespace Noux { * an executable binary (i.e., the init process, * or children created via execve, or * true if the child is a fork from another child + * + * \throw Binary_does_not_exist if child is not a fork and the + * specified name could not be + * looked up at the virtual file + * system */ Child(char const *name, Family_member *parent, @@ -304,6 +311,11 @@ namespace Noux { { _env.pwd(pwd); _args.dump(); + + if (!forked && !_binary_ds.valid()) { + PERR("Lookup of executable \"%s\" failed", name); + throw Binary_does_not_exist(); + } } ~Child() diff --git a/ports/src/noux/main.cc b/ports/src/noux/main.cc index 10b088856..83e40c0cf 100644 --- a/ports/src/noux/main.cc +++ b/ports/src/noux/main.cc @@ -224,34 +224,40 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) j += strlen(src); } - Child *child = new Child(absolute_path.base(), - parent(), - pid(), - _sig_rec, - _root_dir, - Args(_sysio->execve_in.args, - sizeof(_sysio->execve_in.args)), - env, - _env.pwd(), - _cap_session, - _parent_services, - _resources.ep, - false); + try { + Child *child = new Child(absolute_path.base(), + parent(), + pid(), + _sig_rec, + _root_dir, + Args(_sysio->execve_in.args, + sizeof(_sysio->execve_in.args)), + env, + _env.pwd(), + _cap_session, + _parent_services, + _resources.ep, + false); - /* replace ourself by the new child at the parent */ - parent()->remove(this); - parent()->insert(child); + /* replace ourself by the new child at the parent */ + parent()->remove(this); + parent()->insert(child); - _assign_io_channels_to(child); + _assign_io_channels_to(child); - /* signal main thread to remove ourself */ - Genode::Signal_transmitter(_execve_cleanup_context_cap).submit(); + /* signal main thread to remove ourself */ + Genode::Signal_transmitter(_execve_cleanup_context_cap).submit(); - /* start executing the new process */ - child->start(); + /* start executing the new process */ + child->start(); - /* this child will be removed by the execve_finalization_dispatcher */ - return true; + /* this child will be removed by the execve_finalization_dispatcher */ + return true; + } + catch (Child::Binary_does_not_exist) { + _sysio->error.execve = Sysio::EXECVE_NONEXISTENT; } + + return false; } case SYSCALL_SELECT: