[Mono-dev] FW: RealTimeSignal patch

Jonathan Pryor jonpryor at vt.edu
Wed Dec 17 13:05:20 EST 2008


Looking good, but three issues need fixing before we can commit:

1. Formatting.  There are still numerous cases where there isn't a space
before the opening parenthesis.

2. UnixSignal tests that use RealTimeSignum should remain in the
UnixSignalTest class, as these are still testing UnixSignal
functionality, not RealTimeSignum functionality.

3. mono/support/map.h needs to be updated to provide prototypes for the
new functions in mono/support/signal.c.  Installing mono-tools (to get
create-native-map) and running `make refresh` from mono/support will
update mono/support/map.h for you.

BTW, do you have commit access to svn?  If not, I can handle (3) for you
when I commit the patches.

 - Jon

On Wed, 2008-12-17 at 11:19 +0000, tim.jenks at realtimeworlds.com wrote:
> Index: class/Mono.Posix/Mono.Unix.Native/Stdlib.cs
> ===================================================================
> --- class/Mono.Posix/Mono.Unix.Native/Stdlib.cs (revision 121281)
> +++ class/Mono.Posix/Mono.Unix.Native/Stdlib.cs (working copy)
> @@ -504,6 +504,16 @@
>  
>                 public static int SetSignalAction (Signum signal, SignalAction action)
>                 {
> +                       return SetSignalAction(NativeConvert.FromSignum(signal), action);

Missing space before opening parenthesis (2x).

> +               }
> +
> +               public static int SetSignalAction (RealTimeSignum rts, SignalAction action)
> +               {
> +                       return SetSignalAction(NativeConvert.FromRealTimeSignum(rts), action);

Missing space before opening parenthesis (2x).

> +               }
> +               
> +               private static int SetSignalAction (int signum, SignalAction action)
> +               {
>                         IntPtr handler = IntPtr.Zero;
>                         switch (action) {
>                                 case SignalAction.Default:
> @@ -518,7 +528,7 @@
>                                 default:
>                                         throw new ArgumentException ("Invalid action value.", "action");
>                         }
> -                       IntPtr r = sys_signal (NativeConvert.FromSignum (signal), handler);
> +                       IntPtr r = sys_signal (signum, handler);
>                         if (r == _SIG_ERR)
>                                 return -1;
>                         return 0;
> @@ -530,10 +540,14 @@
>                 [CLSCompliant (false)]
>                 public static int raise (Signum sig)
>                 {
> -                       int _sig = NativeConvert.FromSignum (sig);
> -                       return sys_raise (_sig);
> +                       return sys_raise(NativeConvert.FromSignum(sig));

Missing space before opening parenthesis.

>                 }
>  
> +               public static int raise(RealTimeSignum rts)
> +               {
> +                       return sys_raise(NativeConvert.FromRealTimeSignum(rts));

Missing space before opening parenthesis (2x).

> +               }
> +
>                 //
>                 // <stdio.h> -- COMPLETE except for :
>                 //    - the scanf(3) family .
> Index: class/Mono.Posix/Mono.Unix.Native/RealTimeSignum.cs
> ===================================================================
> --- class/Mono.Posix/Mono.Unix.Native/RealTimeSignum.cs (revision 0)
> +++ class/Mono.Posix/Mono.Unix.Native/RealTimeSignum.cs (revision 0)
> @@ -0,0 +1,83 @@
> +//
> +// Authors:
> +//   Tim Jenks (tim.jenks at realtimeworlds.com)
> +//
> +// (C) 2008 Realtime Worlds Ltd
> +//
> +// Permission is hereby granted, free of charge, to any person obtaining
> +// a copy of this software and associated documentation files (the
> +// "Software"), to deal in the Software without restriction, including
> +// without limitation the rights to use, copy, modify, merge, publish,
> +// distribute, sublicense, and/or sell copies of the Software, and to
> +// permit persons to whom the Software is furnished to do so, subject to
> +// the following conditions:
> +//
> +// The above copyright notice and this permission notice shall be
> +// included in all copies or substantial portions of the Software.
> +//
> +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
> +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
> +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
> +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
> +//
> +
> +using System;
> +using System.Runtime.InteropServices;
> +using System.Threading;
> +
> +namespace Mono.Unix.Native {
> +
> +       public struct RealTimeSignum
> +#if NET_2_0
> +               : IEquatable <RealTimeSignum>
> +#endif
> +       {
> +               private int rt_offset;
> +               private static readonly int MaxOffset = UnixSignal.GetSIGRTMAX()-UnixSignal.GetSIGRTMIN()-1;
> +               public static readonly RealTimeSignum MinValue = new RealTimeSignum(0);
> +               public static readonly RealTimeSignum MaxValue = new RealTimeSignum(MaxOffset);

Missing space before opening parenthesis.

Offhand, does C# guarantee the order of initialization of members?  I
don't remember, and if the order isn't guaranteed then we'll need to use
a static constructor to ensure that MaxOffset is set before setting
MaxValue.

> +               public RealTimeSignum(int offset)

Missing space before opening parenthesis.

> +               {
> +                       if (offset < 0)
> +                               throw new ArgumentOutOfRangeException("Offset cannot be negative");

Missing space before opening parenthesis.

> +                       if (offset > MaxOffset)
> +                               throw new ArgumentOutOfRangeException("Offset greater than maximum supported SIGRT");

Missing space before opening parenthesis.

> +                       rt_offset = offset;
> +               }
> +
> +               public int Offset {
> +                       get { return rt_offset; }
> +               }
> +
> +               public override int GetHashCode()

Missing space before opening parenthesis.

I'll stop mentioning these, but there are lots of such spots...

> +               {
> +                       return rt_offset.GetHashCode();
> +               }
> +
> +               public override bool Equals(object obj)
> +               {
> +                       if ((obj == null) || (obj.GetType() != GetType()))
> +                               return false;
> +                       return Equals((RealTimeSignum)obj);
> +               }
> +
> +               public bool Equals(RealTimeSignum value)
> +               {
> +                       return Offset == value.Offset;
> +               }
> +
> +               public static bool operator==(RealTimeSignum lhs, RealTimeSignum rhs)
> +               {
> +                       return lhs.Equals(rhs);
> +               }
> +
> +               public static bool operator!=(RealTimeSignum lhs, RealTimeSignum rhs)
> +               {
> +                       return !lhs.Equals(rhs);
> +               }
> +       }
> +}
> Index: class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs
> ===================================================================
> --- class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs  (revision 121281)
> +++ class/Mono.Posix/Mono.Unix.Native/NativeConvert.cs  (working copy)
> @@ -18,6 +18,24 @@
>                 // Non-generated exports
>                 //
>  
> +               [DllImport (LIB, EntryPoint="Mono_Posix_FromRealTimeSignum")]
> +               private static extern int FromRealTimeSignum(Int32 offset, out Int32 rval);
> +
> +               // convert a realtime signal to os signal
> +               public static int FromRealTimeSignum(RealTimeSignum sig)
> +               {
> +                       int sigNum;
> +                       if (FromRealTimeSignum(sig.Offset, out sigNum) == -1)
> +                               ThrowArgumentException(sig.Offset);
> +                       return sigNum;
> +               }
> +
> +               // convert an offset to an rt signum
> +               public static RealTimeSignum ToRealTimeSignum(int offset)
> +               {
> +                       return new RealTimeSignum(offset);
> +               }
> +
>                 // convert from octal representation.
>                 public static FilePermissions FromOctalPermissionString (string value)
>                 {
> Index: class/Mono.Posix/Test/Mono.Unix.Native/RealTimeSignumTests.cs
> ===================================================================
> --- class/Mono.Posix/Test/Mono.Unix.Native/RealTimeSignumTests.cs       (revision 0)
> +++ class/Mono.Posix/Test/Mono.Unix.Native/RealTimeSignumTests.cs       (revision 0)
> @@ -0,0 +1,180 @@
> +//
> +// RealTimeSignumTests.cs - NUnit Test Cases for Mono.Unix.Native.RealTimeSignum
> +//
> +// Authors:
> +//     Tim Jenks  <tim.jenks at realtimeworlds.com>
> +//
> +// (C) 2008 Realtime Worlds Ltd
> +//
> +
> +using NUnit.Framework;
> +using NUnit.Framework.SyntaxHelpers;
> +using System;
> +using System.Text;
> +using System.Threading;
> +using Mono.Unix;
> +using Mono.Unix.Native;
> +
> +namespace MonoTests.Mono.Unix.Native {
> +
> +       [TestFixture]
> +       public class RealTimeSignumTest 
> +       {
> +
> +               [Test]
> +               public void TestRealTimeCstor()
> +               {
> +                       RealTimeSignum rts = new RealTimeSignum(0);
> +                       using (UnixSignal s = new UnixSignal(rts))
> +                       {
> +                               Assert.That(s.IsRealTimeSignal);
> +                               Assert.That(s.RealTimeSignum, Is.EqualTo(rts));
> +                       }

This is really testing the UnixSignal constructor, so move this test
into UnixSignalTest.

> +               }
> +
> +               [Test]
> +               [ExpectedException(typeof(ArgumentOutOfRangeException))]
> +               public void TestRealTimeOutOfRange()
> +               {
> +                       RealTimeSignum rts = new RealTimeSignum(int.MaxValue);
> +               }
> +

CreateWaitSignalThread() and MultiThreadTest() should be moved to
UnixSignalTest.

> +               // helper method to create a thread waiting on a UnixSignal
> +               static Thread CreateWaitSignalThread(UnixSignal signal, int timeout)
> +               {
> +                       Thread t1 = new Thread(delegate() {
> +                                               DateTime start = DateTime.Now;
> +                                               bool r = signal.WaitOne (timeout, false);
> +                                               DateTime end = DateTime.Now;
> +                                               Assert.AreEqual (signal.Count, 1);
> +                                               Assert.AreEqual (r, true);
> +                                               if ((end - start) > new TimeSpan (0, 0, timeout/1000))
> +                                                       throw new InvalidOperationException ("Signal slept too long");
> +                                       });
> +                       return t1;
> +               }
> +
> +               // helper method to create a two-thread test
> +               static void MultiThreadTest(UnixSignal signal, int timeout, ThreadStart tstart)
> +               {
> +                       Thread t1 = CreateWaitSignalThread(signal, timeout);
> +                       Thread t2 = new Thread(tstart);
> +                       t1.Start();
> +                       t2.Start();
> +                       t1.Join();
> +                       t2.Join();
> +               }
> +
> +               [Test]
> +               [ExpectedException(typeof(ArgumentOutOfRangeException))]
> +               public void TestRealTimeSignumNegativeOffset()
> +               {
> +                       RealTimeSignum rts1 = new RealTimeSignum(-1);
> +               }
> +
> +               [Test]
> +               public void TestRTSignalEquality()
> +               {
> +                       RealTimeSignum rts1 = new RealTimeSignum(0);
> +                       RealTimeSignum rts2 = new RealTimeSignum(0);
> +                       Assert.That(rts1 == rts2, Is.True);
> +                       Assert.That(rts1 != rts2, Is.False);
> +               }
> +
> +               [Test]
> +               public void TestRTSignalInequality()
> +               {
> +                       RealTimeSignum rts1 = new RealTimeSignum(0);
> +                       RealTimeSignum rts2 = new RealTimeSignum(1);
> +                       Assert.That(rts1 == rts2, Is.False);
> +                       Assert.That(rts1 != rts2, Is.True);
> +               }
> +
> +               [Test]
> +               public void TestRTSignalGetHashCodeEquality()
> +               {
> +                       RealTimeSignum rts1 = new RealTimeSignum(0);
> +                       RealTimeSignum rts2 = new RealTimeSignum(0);
> +                       Assert.That(rts1.GetHashCode(), Is.EqualTo(rts2.GetHashCode()));
> +               }
> +
> +               [Test]
> +               public void TestRTSignalGetHashCodeInequality()
> +               {
> +                       RealTimeSignum rts1 = new RealTimeSignum(0);
> +                       RealTimeSignum rts2 = new RealTimeSignum(1);
> +                       Assert.That(rts1.GetHashCode(), Is.Not.EqualTo(rts2.GetHashCode()));
> +               }
> +
> +               [Test]
> +               public void TestIsRTSignalPropertyForRTSignum()
> +               {
> +                       UnixSignal signal1 = new UnixSignal(new RealTimeSignum(0));
> +                       Assert.That(signal1.IsRealTimeSignal, Is.True);
> +               }
> +
> +               [Test]
> +               public void TestIsRTSignalPropertyForSignum()
> +               {
> +                       UnixSignal signal1 = new UnixSignal(Signum.SIGSEGV);
> +                       Assert.That(signal1.IsRealTimeSignal, Is.False);
> +               }
> +
> +               [Test]
> +               public void TestSignumProperty()
> +               {
> +                       UnixSignal signal1 = new UnixSignal(Signum.SIGSEGV);
> +                       Assert.That(signal1.Signum, Is.EqualTo(Signum.SIGSEGV));
> +               }
> +       
> +               [Test]
> +               [ExpectedException]
> +               public void TestSignumPropertyThrows()
> +               {
> +                       UnixSignal signal1 = new UnixSignal(new RealTimeSignum(0));
> +                       Signum s = signal1.Signum;

This should be in UnixSignalTest.

> +               }
> +
> +               [Test]
> +               public void TestRealTimeSignumProperty()
> +               {
> +                       RealTimeSignum rts = new RealTimeSignum(0);
> +                       UnixSignal signal1 = new UnixSignal(rts);
> +                       Assert.That(signal1.RealTimeSignum, Is.EqualTo(rts));

This should be in UnixSignalTest.

> +               }
> +       
> +               [Test]
> +               [ExpectedException]
> +               public void TestRealTimePropertyThrows()
> +               {
> +                       UnixSignal signal1 = new UnixSignal(Signum.SIGSEGV);
> +                       RealTimeSignum s = signal1.RealTimeSignum;

This should be in UnixSignalTest.

> +               }
> +
> +               [Test]
> +               public void TestRaiseRTMINSignal()
> +               {
> +                       RealTimeSignum rts = new RealTimeSignum(0);
> +                       using (UnixSignal signal = new UnixSignal(rts))
> +                       {
> +                               MultiThreadTest(signal, 5000, delegate() {
> +                                       Thread.Sleep(1000);
> +                                       Stdlib.raise(rts);
> +                                       });

This should be in UnixSignalTest.

> +                       }
> +               }
> +
> +               [Test]
> +               public void TestRaiseRTMINPlusOneSignal()
> +               {
> +                       RealTimeSignum rts = new RealTimeSignum(1);
> +                       using (UnixSignal signal = new UnixSignal(rts))
> +                       {
> +                               MultiThreadTest(signal, 5000, delegate() {
> +                                       Thread.Sleep(1000);
> +                                       Stdlib.raise(rts);
> +                                       });

This should be in UnixSignalTest.

> +                       }
> +               }
> +       }
> +}
> Index: class/Mono.Posix/Mono.Posix_test.dll.sources
> ===================================================================
> --- class/Mono.Posix/Mono.Posix_test.dll.sources        (revision 121281)
> +++ class/Mono.Posix/Mono.Posix_test.dll.sources        (working copy)
> @@ -5,4 +5,5 @@
>  Mono.Unix/UnixPathTest.cs
>  Mono.Unix/UnixSignalTest.cs
>  Mono.Unix/UnixUserTest.cs
> +Mono.Unix.Native/RealTimeSignumTests.cs
>  Mono.Unix.Native/StdlibTest.cs
> Index: class/Mono.Posix/Mono.Posix.dll.sources
> ===================================================================
> --- class/Mono.Posix/Mono.Posix.dll.sources     (revision 121281)
> +++ class/Mono.Posix/Mono.Posix.dll.sources     (working copy)
> @@ -34,6 +34,7 @@
>  ./Mono.Unix.Native/MapAttribute.cs
>  ./Mono.Unix.Native/NativeConvert.cs
>  ./Mono.Unix.Native/NativeConvert.generated.cs
> +./Mono.Unix.Native/RealTimeSignum.cs
>  ./Mono.Unix.Native/Stdlib.cs
>  ./Mono.Unix.Native/Syscall.cs
>  ./Mono.Unix.Native/TypeAttributes.cs
> Index: class/Mono.Posix/Mono.Unix/UnixSignal.cs
> ===================================================================
> --- class/Mono.Posix/Mono.Unix/UnixSignal.cs    (revision 121281)
> +++ class/Mono.Posix/Mono.Unix/UnixSignal.cs    (working copy)
> @@ -3,6 +3,7 @@
>  //
>  // Authors:
>  //   Jonathan Pryor (jpryor at novell.com)
> +//   Tim Jenks (tim.jenks at realtimeworlds.com)
>  //
>  // (C) 2008 Novell, Inc.
>  //
> @@ -33,28 +34,55 @@
>  using Mono.Unix.Native;
>  
>  namespace Mono.Unix {
> +
>         public class UnixSignal : WaitHandle {
> -               private Signum signum;
> +               private int signum;
>                 private IntPtr signal_info;
>  
>                 public UnixSignal (Signum signum)
>                 {
> -                       this.signum = signum;
> -                       // ensure signum is a valid signal
> -                       int _signum = NativeConvert.FromSignum (signum);
> -                       this.signal_info = install (_signum);
> +                       this.signum = NativeConvert.FromSignum(signum);
> +                       this.signal_info = install(this.signum);
>                         if (this.signal_info == IntPtr.Zero) {
> -                               throw new ArgumentException ("Unable to handle signal", "signum");
> +                               throw new ArgumentException("Unable to handle signal", "signum");
>                         }
>                 }
>  
> +               public UnixSignal (Mono.Unix.Native.RealTimeSignum rtsig)
> +               {
> +                       signum = NativeConvert.FromRealTimeSignum(rtsig);
> +                        this.signal_info = install(this.signum);

Why is there a space before `this' on this line?

> +                       if (this.signal_info == IntPtr.Zero) {
> +                               throw new ArgumentException("Unable to handle signal", "signum");
> +                       }
> +               }
> +
>                 public Signum Signum {
>                         get {
> +                               if (IsRealTimeSignal)
> +                                       throw new InvalidOperationException("This signal is a RealTimeSignum");
>                                 AssertValid ();

Remove the AssertValid call, and add it to IsRealTimeSignal.

> -                               return signum; 
> +                               return NativeConvert.ToSignum(signum); 
>                         }
>                 }
>  
> +               public RealTimeSignum RealTimeSignum {
> +                       get {
> +                               if (!IsRealTimeSignal)
> +                                       throw new InvalidOperationException("This signal is not a RealTimeSignum");
> +                               return NativeConvert.ToRealTimeSignum(signum-GetSIGRTMIN());
> +                       }
> +               }
> +
> +               public bool IsRealTimeSignal {
> +                       get {

Add an AssertValid(); call here.

> +                               int sigrtmin = GetSIGRTMIN();
> +                               if (sigrtmin == -1)
> +                                       return false;
> +                               return signum >= sigrtmin;
> +                       }
> +               }
> +
>                 [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
>                                 EntryPoint="Mono_Unix_UnixSignal_install")]
>                 private static extern IntPtr install (int signum);
> @@ -67,6 +95,14 @@
>                                 EntryPoint="Mono_Unix_UnixSignal_WaitAny")]
>                 private static extern int WaitAny (IntPtr[] infos, int count, int timeout);
>  
> +               [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
> +                                EntryPoint="Mono_Posix_SIGRTMIN")]
> +               internal static extern int GetSIGRTMIN();
> +
> +               [DllImport (Stdlib.MPH, CallingConvention=CallingConvention.Cdecl,
> +                                EntryPoint="Mono_Posix_SIGRTMAX")]
> +               internal static extern int GetSIGRTMAX();
> +
>                 private void AssertValid ()
>                 {
>                         if (signal_info == IntPtr.Zero)
> 



More information about the Mono-devel-list mailing list