Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASL] Semantics of throw statement #899

Closed
maranget opened this issue Jul 10, 2024 · 2 comments
Closed

[ASL] Semantics of throw statement #899

maranget opened this issue Jul 10, 2024 · 2 comments

Comments

@maranget
Copy link
Member

Hi @HadrienRenaud. the semantics of throw looks too eager in the concurrent case. Consider the following test:

ASL U

{}

type  Coucou of exception {};

func f(x:integer) => integer
begin
  if x == 0 then
    throw Coucou {  };  
  end
  return x;
end

func main() => integer
begin
  try
    let z = f(0);
    print(z);
  catch
    when Coucou =>
      print(1010);
  end
  return 0;
end

Executing the above test with herd7 U.litmus results in printing 1010 twice.

Even more serious we have a fatal error when the exception has an argument:

ASL T

{}

type  Coucou of exception {z:integer};

func f(x:integer) => integer
begin
  if x == 0 then
    throw Coucou { z=x };  
  end
  return x;
end

func main() => integer
begin
  try
    let z = f(0);
    print(z);
  catch
    when e:Coucou =>
      print (e.z);
  end
  return 0;
end

Running the test results in a fatal error:

% herd7 T.litmus
0
0
Contradiction on reg 0:thrown-1: loaded {z:0,} vs. stored 0

Fatal: File "T.litmus" Adios
Fatal error: exception File "herd/mem.ml", line 837, characters 16-22: Assertion failed
@maranget
Copy link
Member Author

Thinking twice, it is normal for the print statement to be executed twice. However, the fatal error is an actual bug.

@maranget
Copy link
Member Author

maranget commented Jul 11, 2024

Here is a simpler example:

ASL U

{ }

type  Coucou of exception {};

func f(a:integer) => integer
begin
  let b = SomeBoolean();
  if b then
    throw Coucou { };  
  end
  return a;
end

func main() => integer
begin
  let x=0;
  try
    let z = f(x);
    print(z);
  catch
    when Coucou =>
      assert TRUE;
  end
  return 0;
end

Running the test above, we have:

% herd7 U.litmus
0
0
Warning: Uncaught exception: Coucou {}

maranget added a commit that referenced this issue Jul 22, 2024
[asl] Fix the interpretation of the asl try statement.

Fix for issue #899. Here is an inlined version of the problematic test:
```
ASL U1

{ }

type  Coucou of exception {};

func g(a:integer) => integer
begin
  try
    let b = SomeBoolean();
    if b then
      throw Coucou {};
    end
    return a+1;
  catch
    when Coucou =>
      return a+3;
  end

end
func main() => integer
begin
  let  x = g(0);
  return 0;
end

locations [0:main.0.x;]
```
Executing this test with the previous **herd7** yields a fatal error due to the duplicated execution of the statement `<S>`  from the  `try <S> catch` construct.
```
% herd7  U1.litmus
Warning: Uncaught exception: Coucou {}
```
Namely, in the case when no exception is thrown, `<S>` is re-executed unprotected, resulting in an uncaught exception fault.
maranget added a commit that referenced this issue Jul 25, 2024
[herd,asl] Fix asl throw propagation
 Monad argument was discarded bin the monad combinator `bind_env` when an exception was raised.

As for PR #902 and #899, any monad argument to combinators has to be used linearly. Here is a test that illustrates the bug:
```
ASL throw-assign

{}

var z = 0;

type Coucou of exception;

func f() => integer
begin
  z = 2;
  throw Coucou {};
end

func main() => integer
begin
  try
    z = f();
  catch
    when Coucou => return 0;
  end
end

forall 0:z=2
```
Before the fix the events related to the global assignment `z = 2` were discarded and the final value of `z` was zero.
maranget added a commit that referenced this issue Jul 26, 2024
[herd,asl] Fix duplicated execution of catcher statement

Fix double execution of matched catcher statement. Here is an illustrative test:
```
ASL catch-exec-twice

{}

type Bonga of exception;

func g() => integer
begin
  try
    throw Bonga {};
  catch
    when Bonga =>
      let coucou = 11 ;
      __DEBUG__(coucou);
  end
  return 0;
end

func main() => integer
begin  
  return g();
end
```
Due to the implementation of the "_implicit re-throw_" mechanism, the catcher statement `let coucou = 11; __DEBUG__(coucou);` was executed twice, resulting in printing the debug message twice.

The bug originates  in a non-linear usage of a monad argument, similarly to PR #909, #902 and #899.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant