~ chicken-core (chicken-5) 1186f2232a686f0bfd92f7be3de9784cf4c6f2d3


commit 1186f2232a686f0bfd92f7be3de9784cf4c6f2d3
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Fri Aug 13 06:25:01 2010 -0400
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Fri Aug 13 06:25:01 2010 -0400

    check callbacks for returning twice

diff --git a/distribution/manifest b/distribution/manifest
index 158c4385..6c2ceb82 100644
--- a/distribution/manifest
+++ b/distribution/manifest
@@ -160,6 +160,7 @@ tests/private-repository-test.scm
 tests/records-and-setters-test.scm
 tests/dwindtst.scm
 tests/dwindtst.expected
+tests/callback-tests.scm
 tweaks.scm
 utils.scm
 apply-hack.x86.S
diff --git a/runtime.c b/runtime.c
index 730fb6f9..688ca5ff 100644
--- a/runtime.c
+++ b/runtime.c
@@ -1737,7 +1737,7 @@ C_word C_fcall C_callback(C_word closure, int argc)
   jmp_buf prev;
   C_word 
     *a = C_alloc(2),
-    k = C_closure(&a, 1, (C_word)callback_return_continuation);
+    k = C_closure(&a, 2, (C_word)callback_return_continuation, C_SCHEME_FALSE);
   int old = chicken_is_running;
 
   if(old && C_block_item(callback_continuation_stack_symbol, 0) == C_SCHEME_END_OF_LIST)
@@ -1800,8 +1800,12 @@ C_word C_fcall C_callback_wrapper(void *proc, int argc)
 
 void C_ccall callback_return_continuation(C_word c, C_word self, C_word r)
 {
+  if(C_block_item(self, 1) == C_SCHEME_TRUE)
+    panic(C_text("callback returned twice"));
+
   assert(callback_returned_flag == 0);
   callback_returned_flag = 1;
+  C_set_block_item(self, 1, C_SCHEME_TRUE);
   C_save(r);
   C_reclaim(NULL, NULL);
 }
diff --git a/tests/callback-tests.scm b/tests/callback-tests.scm
new file mode 100644
index 00000000..afac01ee
--- /dev/null
+++ b/tests/callback-tests.scm
@@ -0,0 +1,20 @@
+;;;; callback-tests.scm
+
+
+(define k1)
+
+(define-external (foo) void
+  (call/cc
+   (lambda (k) (set! k1 k)))
+  (print "hi!"))
+
+#>
+extern void foo();
+static void bar() { foo(); }
+<#
+
+(print "callbacks ...")
+((foreign-safe-lambda void "bar"))
+
+(when (member "twice" (command-line-arguments))
+  (k1 #f))
diff --git a/tests/runtests.sh b/tests/runtests.sh
index 804edb17..e2c2eab6 100644
--- a/tests/runtests.sh
+++ b/tests/runtests.sh
@@ -73,6 +73,17 @@ fi
 
 diff -bu scrutiny.out scrutiny.expected
 
+echo "======================================== callback tests ..."
+$compile callback-tests.scm
+./a.out
+
+if ./a.out twice; then
+    echo "double-return from callback didn't fail"
+    exit 1
+else
+    echo "double-return from callback failed as it should."
+fi
+
 echo "======================================== runtime tests ..."
 $interpret -s apply-test.scm
 $compile test-gc-hooks.scm
@@ -126,7 +137,7 @@ $compile compiler-syntax-tests.scm
 ./a.out
 
 echo "======================================== import tests ..."
-$interpret import-tests.scm
+$interpret -bnq import-tests.scm
 
 echo "======================================== import library tests ..."
 rm -f ../foo.import.* foo.import.*
Trap