On Mon, Oct 16, 2017 at 4:30 AM, Justin Cinkelj <justin.cink...@xlab.si>
wrote:

> The previous patch (namespace: enable per namespace alarm/signal)
> implemented per elf namespace signals for common usecase of alarms.
>
> But, as Nadav explained, it failed to allow application in a separate
> ELF namespace to install its own handler for signals related to a
> page fault, division by zero, and similar exceptions.
> See also https://groups.google.com/forum/#!topic/osv-dev/AlYM5i4laPM
>
> The apps/apache-spark is one such example. It installs its own handler
> for SIGSEGV. Without this patch, the app started in initial/main ELF
> namespace only. But it failed to start in a new ELF namespace.
>
> This patch fixes this. Instead of always using signal_actions variable,
> we ask current application/ELF namespace for its copy of signal_actions,
> and use that one when generating signal.
>

Thanks. Your implementation is even nicer than I suggested (you wierdified
a low-level
function to get the array, keeping the more interesting functions sane).

But I have a few suggestions for further improvement below:


>
> Signed-off-by: Justin Cinkelj <justin.cink...@xlab.si>
> ---
>  core/app.cc        |  9 +++++++++
>  include/osv/app.hh | 11 +++++++++++
>  libc/signal.cc     | 13 ++++++++++---
>  3 files changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/core/app.cc b/core/app.cc
> index 325ae820..acd9f611 100644
> --- a/core/app.cc
> +++ b/core/app.cc
> @@ -18,6 +18,7 @@
>  #include <boost/range/algorithm/transform.hpp>
>  #include <osv/wait_record.hh>
>  #include "libc/pthread.hh"
> +#include "libc/signal.hh"
>
>  using namespace boost::range;
>
> @@ -480,6 +481,14 @@ void application::clone_osv_environ()
>      }
>  }
>
> +struct sigaction* application::get_signal_actions() {
> +    if (_libsignal == nullptr) {
> +        // running in initial ELF namespace
> +        return signal_actions;
> +    }
> +    return _libsignal->lookup<struct sigaction>("_ZN3osv14signal_
> actionsE");
>


Looking at this implementation made me think: If we already have the "app"
structure, and use its "_libsignal" field,
why not add another app field, like signal_actions? I.e., when setting
_libsignal you could also set _signal_actions - using
the same lookup you did here - and then use it in the get_signal_actions
method. The benefit would be to avoid
the relatively complex and slow lookup code on every signal.
This is not critical (I don't think there's a huge number of signals), but
may make a difference when there are plenty of
SIGSEGV signals (I was worried this is the case in Java, I don't remember
if it's true) - what do you think?

Another thing is that I'm not happy about the need for the mangled name in
this code - the mangling scheme may change
in future versions of the compiler or different architectures or different
compilers or whatever. One thing we could do is to move
the signal_actions out of the osv namespace so it will have a normal
non-mangled name. Another idea could be to have an
"extern C" function in signal.cc, say, get_signal_actions() (this will be
in signal.cc, not app.cc!) which returns osv::signal_actions
(which could be made "static", I don't know why it isn't now...) - and then
the code which sets app._signal_actions will lookup and
call this function instead of looking up a variable directly..




> +}
> +
>  void application::set_environ(const std::string &key, const std::string
> &value,
>                                bool new_program)
>  {
> diff --git a/include/osv/app.hh b/include/osv/app.hh
> index d3015515..0c3149fb 100644
> --- a/include/osv/app.hh
> +++ b/include/osv/app.hh
> @@ -19,6 +19,7 @@
>  #include <list>
>  #include <unordered_map>
>  #include <string>
> +#include <api/signal.h>
>
>  extern "C" void __libc_start_main(int(*)(int, char**), int, char**,
> void(*)(),
>      void(*)(), void(*)(), void*);
> @@ -183,6 +184,16 @@ public:
>      std::shared_ptr<elf::object> lib() const { return _lib; }
>
>      elf::program *program();
> +
> +    /**
> +      * Returns signal handlers of the current app (elf namespace).
> +      *
> +      * This is used to implement per-elf-namespace signal handling,
> +      * when signal is called from the OSv kernel (for example, when
> +      * application in a separate elf namespace generates SIGSEGV, and has
> +      * installed a handler).
> +      */
> +    struct sigaction* get_signal_actions();
>  private:
>      void new_program();
>      void clone_osv_signal();
> diff --git a/libc/signal.cc b/libc/signal.cc
> index 1992ff88..b65bff2a 100644
> --- a/libc/signal.cc
> +++ b/libc/signal.cc
> @@ -18,6 +18,7 @@
>  #include <osv/clock.hh>
>  #include <api/setjmp.h>
>  #include <osv/stubbing.hh>
> +#include <osv/app.hh>
>
>  using namespace osv::clock::literals;
>
> @@ -123,11 +124,17 @@ void generate_signal(siginfo_t &siginfo,
> exception_frame* ef)
>          // needs to be running to generate them. So definitely not
> waiting.
>          abort();
>      }
> -    if (is_sig_dfl(signal_actions[siginfo.si_signo])) {
> +
> +    // Application in elf namespace have different signal handler than
> main
> +    // OSv kernel. Use it if it is installed.
> +    auto app_signal_actions = application::get_current().
> get()->get_signal_actions();
>

Is this ".get()" necessary? Wouldn't just
get_current()->get_signal_actions() do the right thing?
BTW, I don't remember, does get_current() always work? Don't we need to
check if it's zero or something? (I really don't remember and I'm not
looking at the code now).


> +    assert(app_signal_actions);
> +
> +    if (is_sig_dfl(app_signal_actions[siginfo.si_signo])) {
>          // Our default is to abort the process
>          abort();
> -    } else if(!is_sig_ign(signal_actions[siginfo.si_signo])) {
> -        arch::build_signal_frame(ef, siginfo, signal_actions[siginfo.si_
> signo]);
> +    } else if(!is_sig_ign(app_signal_actions[siginfo.si_signo])) {
> +        arch::build_signal_frame(ef, siginfo,
> app_signal_actions[siginfo.si_signo]);
>      }
>  }
>
> --
> 2.13.6
>
> --
> You received this message because you are subscribed to the Google Groups
> "OSv Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to osv-dev+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to