Posix RTS test fixes and Android compatibility
authorMarek Habersack <grendel@twistedcode.net>
Mon, 3 Aug 2015 14:48:25 +0000 (10:48 -0400)
committerMarek Habersack <grendel@twistedcode.net>
Thu, 13 Aug 2015 09:53:28 +0000 (11:53 +0200)
Android's libc (bionic) defines the _GNU_SOURCE macro but fails to adhere
to the GNU sematics in (at least) one case - the strerror_r function.
The function follows XSI semantics instead of the GNU one which caused our
code to segfault on Android. This patch special-cases Android to use the XSI
semantics for strerror_r. This un-breaks some POSX real-time singals tests.

It also makes provisions for detecting whether the real-time signals are safe
to use on the current platform. They are safe for all platforms desktop Mono
runs on, but they're not safe on most Android platforms.

mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
mcs/class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs
mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs [new file with mode: 0644]
mcs/class/Mono.Posix/Test/Mono.Unix.Native/RealTimeSignumTests.cs
mcs/class/Mono.Posix/Test/Mono.Unix/UnixSignalTest.cs
support/errno.c

index 270b0b6aee680cb64332b06638110b58a6eda18b..0f84821b52ee01392b762e7b76723da1306510b2 100644 (file)
@@ -6,5 +6,6 @@ Mono.Unix/UnixMarshalTest.cs
 Mono.Unix/UnixPathTest.cs
 Mono.Unix/UnixSignalTest.cs
 Mono.Unix/UnixUserTest.cs
+Mono.Unix.Android/TestHelper.cs
 Mono.Unix.Native/RealTimeSignumTests.cs
 Mono.Unix.Native/StdlibTest.cs
index ffa329f1b5bf3d5fa7cc75a7a6e93355b118d117..4e2613b127991263f8ba2d31fede7f7da2a99f1f 100644 (file)
@@ -17,10 +17,10 @@ namespace Mono.Unix.Native {
                //
                // Non-generated exports
                //
-
+#if !MONODROID
                [DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
                private static extern int FromRealTimeSignum (Int32 offset, out Int32 rval);
-
+#endif
                // convert a realtime signal to os signal
                public static int FromRealTimeSignum (RealTimeSignum sig)
                {
diff --git a/mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs b/mcs/class/Mono.Posix/Test/Mono.Unix.Android/TestHelper.cs
new file mode 100644 (file)
index 0000000..a7a56a4
--- /dev/null
@@ -0,0 +1,12 @@
+namespace Mono.Unix.Android
+{
+       // Another version of this class is used by the Xamarin.Android test suite
+       // It is here to keep the test code #ifdef free as much as possible
+       public class TestHelper
+       {
+               public static bool CanUseRealTimeSignals ()
+               {
+                       return true;
+               }
+       }
+}
\ No newline at end of file
index 4aea4e8ba60f4db71577c3f9789c4c6333bab39f..f68fe53b8ce70b896dbb603a9530042fddae1885 100644 (file)
@@ -15,6 +15,7 @@ using System;
 using System.Text;
 using System.Threading;
 using Mono.Unix;
+using Mono.Unix.Android;
 using Mono.Unix.Native;
 
 namespace MonoTests.Mono.Unix.Native {
@@ -27,6 +28,8 @@ namespace MonoTests.Mono.Unix.Native {
                [ExpectedException (typeof (ArgumentOutOfRangeException))]
                public void TestRealTimeOutOfRange ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (int.MaxValue);
                }
 
@@ -34,12 +37,16 @@ namespace MonoTests.Mono.Unix.Native {
                [ExpectedException (typeof (ArgumentOutOfRangeException))]
                public void TestRealTimeSignumNegativeOffset ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (-1);
                }
 
                [Test]
                public void TestRTSignalEquality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (0);
                        Assert.That (rts1 == rts2, Is.True);
@@ -49,6 +56,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalInequality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (1);
                        Assert.That (rts1 == rts2, Is.False);
@@ -58,6 +67,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalGetHashCodeEquality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (0);
                        Assert.That (rts1.GetHashCode (), Is.EqualTo(rts2.GetHashCode ()));
@@ -66,6 +77,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestRTSignalGetHashCodeInequality ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts1 = new RealTimeSignum (0);
                        RealTimeSignum rts2 = new RealTimeSignum (1);
                        Assert.That (rts1.GetHashCode (), Is.Not.EqualTo(rts2.GetHashCode ()));
@@ -74,6 +87,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestIsRTSignalPropertyForRTSignum ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal(new RealTimeSignum (0));
                        Assert.That (signal1.IsRealTimeSignal, Is.True);
                }
@@ -81,6 +96,8 @@ namespace MonoTests.Mono.Unix.Native {
                [Test]
                public void TestIsRTSignalPropertyForSignum ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
                        Assert.That (signal1.IsRealTimeSignal, Is.False);
                }
index b7b4e6fc695e9539dc22237d55b0b1a45c766ff2..f88defeaff50b92118b6d1f2fec9d742ce00a208 100644 (file)
@@ -15,6 +15,7 @@ using System;
 using System.Text;
 using System.Threading;
 using Mono.Unix;
+using Mono.Unix.Android;
 using Mono.Unix.Native;
 #if !MONODROID
 namespace NUnit.Framework.SyntaxHelpers { class Dummy {} }
@@ -127,6 +128,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimeCstor ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        using (UnixSignal s = new UnixSignal (rts))
                        {
@@ -140,6 +143,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestSignumPropertyThrows ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (new RealTimeSignum (0));
                        Signum s = signal1.Signum;
                }
@@ -148,6 +153,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimeSignumProperty ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        UnixSignal signal1 = new UnixSignal (rts);
                        Assert.That (signal1.RealTimeSignum, Is.EqualTo (rts));
@@ -158,6 +165,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRealTimePropertyThrows ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        UnixSignal signal1 = new UnixSignal (Signum.SIGSEGV);
                        RealTimeSignum s = signal1.RealTimeSignum;
                }
@@ -166,6 +175,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRaiseRTMINSignal ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        RealTimeSignum rts = new RealTimeSignum (0);
                        using (UnixSignal signal = new UnixSignal (rts))
                        {
@@ -180,6 +191,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestRaiseRTMINPlusOneSignal ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        /*this number is a guestimate, but it's ok*/
                        for (int i = 1; i < 10; ++i) {
                                RealTimeSignum rts = new RealTimeSignum (i);
@@ -205,6 +218,8 @@ namespace MonoTests.Mono.Unix {
                [Category ("NotOnMac")]
                public void TestCanRegisterRTSignalMultipleTimes ()
                {
+                       if (!TestHelper.CanUseRealTimeSignals ())
+                               return;
                        /*this number is a guestimate, but it's ok*/
                        for (int i = 1; i < 10; ++i) {
                                RealTimeSignum rts = new RealTimeSignum (i);
index 26ee780169183aff8538e23987818f38721356f4..384451da47c4af2149080cad2de18498e7be577b 100644 (file)
@@ -35,7 +35,7 @@ Mono_Posix_Stdlib_SetLastError (int error_number)
  * we assume that the XPG version is present.
  */
 
-#ifdef _GNU_SOURCE
+#ifdef _GNU_SOURCE && !PLATFORM_ANDROID
 #define mph_min(x,y) ((x) <= (y) ? (x) : (y))
 
 /* If you pass an invalid errno value to glibc 2.3.2's strerror_r, you get
@@ -80,7 +80,27 @@ Mono_Posix_Syscall_strerror_r (int errnum, char *buf, mph_size_t n)
        mph_return_if_size_t_overflow (n);
 
        /* first, check for valid errnum */
+#if PLATFORM_ANDROID
+       /* Android NDK defines _GNU_SOURCE but strerror_r follows the XSI semantics
+        * not the GNU one. XSI version returns an integer, as opposed to the GNU one
+        * which returns pointer to the buffer.
+        */
+       if (strerror_r (errnum, ebuf, sizeof(ebuf)) == -1) {
+               /* XSI strerror_r will return -1 if errno is set, but if we leave the value
+                * alone it breaks Mono.Posix StdioFileStream tests, so we'll ignore the value
+                * and set errno as below
+                */
+               errno = EINVAL;
+               return -1;
+       }
+       r = ebuf;
+#else
        r = strerror_r (errnum, ebuf, sizeof(ebuf));
+#endif
+       if (!r) {
+               errno = EINVAL;
+               return -1;
+       } 
        len = strlen (r);
 
        if (r == ebuf ||