Kumpera: Please see Option #5, at end.

On Sep 16, 2016, at 10:59 AM, Sebastien Pouliot via android-devel 
<android-de...@lists.dot.net> wrote:
> The current sequence of events is this:
> a) The app launches, and Xamarin.iOS initializes the Mono runtime.

Which raises Plausible Solution #0: structure things such that the 3rd party 
lib sets the default signal handler *before* mono is initialized.

This could be done by e.g. using a C++ global object in an archive linked into 
the main binary: the constructor will be executed before `main()` executes, so 
by the time mono has initialized it will see the 3rd party SIGSEGV handler, not 
the system handler.

There are problems with this:

1. Before `main()`, execution order of global constructors is undefined. This 
solution is “scalable”, in that any number of libraries can participate, but 
the order between those libraries can’t be controlled.

2. It requires that the 3rd party library be create-able in this fashion. For 
example, if it uses a license key which is only available in managed code, this 
can’t work.

3. It only works for *app* projects. This can thus work for Xamarin.iOS, but it 
*can’t* work for Xamarin.Android, which uses shared libraries.

However, we can apply similar Judo to make things work in Xamarin.Android. Mono 
is initialized on Android through a ContentProvider with a high 
//provider/@android:initOrder value; the `initOrder` value controls the order 
of loading ContentProviders. You could thus set things up so that the 3rd party 
lib uses a Java ContentProvider with a *higher* `initOrder` value, thus 
ensuring that the 3rd party lib is initialized *before* Xamarin.Android. Mono 
will thus see the 3rd party’s SIGSEGV handler, not the system one.

The immediate problem here is that Xamarin.Android sets the initOrder value to 
int.MaxValue, but we can certainly lower the value we use to allow code to 
execute before the Xamarin.Android bootstrap code…

Pro: works/can be made to work *now*, with minimal/no changes to mono and 

Con: Requires modifying process state before Mono starts executing, which isn’t 
always easy or straightforward (requires native code).

> b) Managed code starts running, and the actual app initializes any 
> third-party libraries. At this point third-party libraries typipcally do 
> something like this:

This is assuming/requiring that the 3rd party code is managed code. When it 
comes to signal handlers, I don’t think that’s valid; any reasonably sane 
SIGSEGV-handling code *must* be native. Thus, we don’t necessarily need to 
support initializing it *during* execution of managed code.

That might still be a good idea… I’m not sure, myself.

> A couple of ideas:
> 1) Add an API to select/set the signal handler Mono chains to:
> namespace ObjCRuntime {
>       public class Runtime {
>             public struct SigAction
>             {
>                   public IntPtr Handler; //
>                   public uint Mask; // sa_mask => sigset_t => 
> __darwin_sigset_t => uint32_t
>                   public int Flags; // sa_flags => int
>             }
>             public static bool InstallSignalHandler (int signal, SigAction 
> handler, out SigAction previous_handler);
>       }
> }

I would prefer to *not* expose a managed binding of `struct sigaction`, in part 
to reduce portability issues. On Android, `sigset_t` is `unsigned long`, so on 
64-bit platforms this will be a 64-bit value, not a 32-bit value, so this 
wouldn’t be compatible.

Granted, we could have “parallel” definitions for Android vs. iOS, but if we’re 
doing to define a new API, we should try to minimize such things. :-)

> 2) Add an attribute that gives the name of the signal handler, and then 
> Xamarin.iOS generates the required code to make sure these signal handlers 
> are called for signals Mono doesn't handle:

Such an attribute would need to be iOS/Mac-specific; there’s no Android 
equivalent. It would also require that `third_party_signal_handler` be a public 
symbol that the linker can find, in addition to the “use before initialized” 
issue that Rolf notes.

I think Solution #0 (global C++ objects) overlaps with this general idea, and 
is cleaner to boot.

> 3) A mix of both of the above:
>       ObjCRuntime.Runtime.EnableCustomSignalHandler (Signals.SIGSEGV, 
> "third_party_signal_handler");
>    The problem here is that we'd have to use dlsym to lookup the function 
> pointer for third_party_signal_handler, which can be problematic sometimes 
> (#1 just gets the function pointer from the signal handler the native 
> third-party library installed, and for #2 generate native code that 
> references the function instead).

Another issue: the signals that are specified are signals that Mono needs to 
handle *first*. I’m not sure that this list of signals is/should be set in 
stone; what if Mono needs to be first for processing SIGILL in the future? Then 
this code will be out-of-date, possibly resulting on obscure errors.

This doesn’t feel “safe” to me

>  4) A mix of all of the above:
> Any other ideas? Suggestions for better naming for the API?

Option 5: a “new" Mono function.

The fundamental problem is that Mono *must* be the first signal handler for 
e.g. SIGSEGV, but ~anybody else can replace the SIGSEGV handler at any time.

What if the Mono team made one of the following function public:

        // in: https://github.com/mono/mono/blob/master/mono/mini/mini-posix.c
        void mono_runtime_install_handlers (void);
        void mono_runtime_posix_install_handlers (void);

My quick reading of `mono_runtime_posix_install_handlers()` (line ~470) 
suggests that it registers those signals. It’s currently “internal”, i.e. you 
can’t `dlsym()` that function from `libmonosgen-2.0.dylib`, but if it were 
public, you could then register all your third party library code, then call 
`mono_runtime_install_handlers()`, and the app would be fine.

There would be a problem if e.g. a null value was used in between 3rd party 
crash handler registration and use of `mono_runtime_install_handlers()`, but 
such issues should be minimized with appropriate coding, and these issues exist 
in e.g. current practice.

 - Jon

Mono-devel-list mailing list

Reply via email to