[Mono-list] patch for mono/jit/exception.c
Linus Upson
linus@linus.com
Sat, 4 May 2002 22:48:01 -0700
This is a multi-part message in MIME format.
------=_NextPart_000_0019_01C1F3BD.BEDB82F0
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Attached is a test class mcs/class/corlib/Test/System/ExceptionTest.cs
which implements an NUnit test case for the exception described
previously. Also attached is the corresponding patch for
System/AllTests.cs. The ExceptionTest class only tests for this one
issue and so isn't a very good test of the Exception class as a whole. I
don't know if you want to include stub tests like this or not.
Linus
-----Original Message-----
From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com] On
Behalf Of Linus Upson
Sent: Saturday, May 04, 2002 2:39 PM
To: mono-list@ximian.com
Subject: RE: [Mono-list] patch for mono/jit/exception.c
I forgot to include the small test program which demonstrates the
problem:
using System;
public class TryTest {
public static void ThrowException() {
throw new Exception();
}
public static void Main() {
ThrowException();
// If the following line is uncommented, mono will work
right.
// Console.WriteLine("This shouldn't matter");
try {
Console.WriteLine("In try block");
} catch (Exception e) {
Console.WriteLine("------------------------");
Console.WriteLine(e);
Console.WriteLine("------------------------");
}
}
}
Before the patch, the Exception thrown in ThrowException() would be
caught by the catch block in Main().
Linus
-----Original Message-----
From: mono-list-admin@ximian.com [mailto:mono-list-admin@ximian.com] On
Behalf Of Linus Upson
Sent: Saturday, May 04, 2002 2:09 PM
To: mono-list@ximian.com
Subject: [Mono-list] patch for mono/jit/exception.c
Running NUnitConsole_mono.exe in mono on Windows exposed the following
bug:
If an exception were throw by the instruction immediately preceding a
try block, the exception would be considered to be thrown inside the try
block.
A patch is attached which appears to solve the problem. The patch won't
work if arch_handle_exception() can be called with ctx->SC_EIP pointing
to the instruction which threw the exception. I think an exception can
only be thrown by a CALL (as far as managed code is concerned) so EIP
will always point to the instruction after the CALL. If this isn't the
case, a different fix will be needed.
I believe the same problem exists on Linux as well, but I haven't
tested.
Cheers,
Linus
_______________________________________________
Mono-list maillist - Mono-list@ximian.com
http://lists.ximian.com/mailman/listinfo/mono-list
------=_NextPart_000_0019_01C1F3BD.BEDB82F0
Content-Type: text/plain;
name="ExceptionTest.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="ExceptionTest.cs"
//
// ExceptionTest.cs - NUnit Test Cases for the System.Exception class
//=20
// Linus Upson (linus@linus.com)
//
using System;
using NUnit.Framework;
namespace MonoTests.System
{
public class ExceptionTest : TestCase
{
public ExceptionTest() : base ("MonoTests.System.ExceptionTest =
testsuite") {}
public ExceptionTest(string name) : base(name) {}
=09
public static ITest Suite {
get {
return new TestSuite(typeof(ExceptionTest));
}
}
=09
// This test makes sure that exceptions thrown on block boundaries are
// handled in the correct block. The meaning of the 'caught' variable =
is
// a little confusing since there are two catchers: the method being
// tested the the method calling the test. There is probably a better
// name, but I can't think of it right now.
=09
public void TestThrowOnBlockBoundaries()
{
bool caught;
=09
try {
caught =3D false;
ThrowBeforeTry();
} catch {
caught =3D true;
}
Assert("Exceptions thrown before try blocks should not be caught", =
caught);
=09
try {
caught =3D false;
ThrowAtBeginOfTry();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at begin of try blocks should be caught", =
!caught);
try {
caught =3D false;
ThrowAtEndOfTry();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at end of try blocks should be caught", =
!caught);
try {
caught =3D false;
ThrowAtBeginOfCatch();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at begin of catch blocks should not be =
caught", caught);
try {
caught =3D false;
ThrowAtEndOfCatch();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at end of catch blocks should not be =
caught", caught);
try {
caught =3D false;
ThrowAtBeginOfFinally();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at begin of finally blocks should not be =
caught", caught);
try {
caught =3D false;
ThrowAtEndOfFinally();
} catch {
caught =3D true;
}
Assert("Exceptions thrown at end of finally blocks should not be =
caught", caught);
try {
caught =3D false;
ThrowAfterFinally();
} catch {
caught =3D true;
}
Assert("Exceptions thrown after finally blocks should not be caught", =
caught);
}
=09
private static void DoNothing()
{
}
private static void ThrowException()
{
throw new Exception();
}
=09
private static void ThrowBeforeTry()
{
ThrowException();
try {
DoNothing();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtBeginOfTry()
{
DoNothing();
try {
ThrowException();
DoNothing();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtEndOfTry()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
}
}
private static void ThrowAtBeginOfCatch()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
throw;
}
}
private static void ThrowAtEndOfCatch()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
throw;
}
}
private static void ThrowAtBeginOfFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
ThrowException();
DoNothing();
}
}
private static void ThrowAtEndOfFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
DoNothing();
ThrowException();
}
}
private static void ThrowAfterFinally()
{
DoNothing();
try {
DoNothing();
ThrowException();
} catch (Exception) {
DoNothing();
} finally {
DoNothing();
}
ThrowException();
}
}
}
------=_NextPart_000_0019_01C1F3BD.BEDB82F0
Content-Type: application/octet-stream;
name="System.AllTests.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="System.AllTests.patch"
Index: class/corlib/Test/System/AllTests.cs=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /mono/mcs/class/corlib/Test/System/AllTests.cs,v=0A=
retrieving revision 1.20=0A=
diff -u -r1.20 AllTests.cs=0A=
--- class/corlib/Test/System/AllTests.cs 30 Apr 2002 19:19:04 -0000 1.20=0A=
+++ class/corlib/Test/System/AllTests.cs 5 May 2002 05:38:49 -0000=0A=
@@ -49,6 +49,7 @@=0A=
suite.AddTest (UInt64Test.Suite);=0A=
suite.AddTest (VersionTest.Suite);=0A=
suite.AddTest (MulticastDelegateTest.Suite);=0A=
+ suite.AddTest (ExceptionTest.Suite);=0A=
return suite;=0A=
}=0A=
}=0A=
------=_NextPart_000_0019_01C1F3BD.BEDB82F0--