aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/testdata
diff options
context:
space:
mode:
authorSimon Ferquel <simon.ferquel@docker.com>2019-08-05 11:28:52 +0000
committerAlex Brainman <alex.brainman@gmail.com>2019-08-31 00:47:27 +0000
commite5e5fb024a228b200d474b030deb4998af4c45f1 (patch)
tree9f36f330e425ca0a9e5f036958d9a4d6b1f9990e /src/runtime/testdata
parent1786ecd502364ac92493acbdee5ddca50c80afde (diff)
downloadgo-e5e5fb024a228b200d474b030deb4998af4c45f1.tar.xz
runtime: do not crash in lastcontinuehandler when running as DLL
If Go DLL is used by external C program, and lastcontinuehandler is reached, lastcontinuehandler will crash the process it is running in. But it should not be up to Go runtime to decide if process to be crashed or not - it should be up to C runtime. This CL adjusts lastcontinuehandler to not to crash when running as DLL. Fixes #32648. Change-Id: Ia455e69b8dde2a6f42f06b90e8af4aa322ca269a GitHub-Last-Rev: dbdffcb43206e94ef130ecadd1c82a8763225ac2 GitHub-Pull-Request: golang/go#32574 Reviewed-on: https://go-review.googlesource.com/c/go/+/181839 Run-TryBot: Alex Brainman <alex.brainman@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Diffstat (limited to 'src/runtime/testdata')
-rw-r--r--src/runtime/testdata/testwinlib/main.c57
-rw-r--r--src/runtime/testdata/testwinlib/main.go28
2 files changed, 85 insertions, 0 deletions
diff --git a/src/runtime/testdata/testwinlib/main.c b/src/runtime/testdata/testwinlib/main.c
new file mode 100644
index 0000000000..e84a32f753
--- /dev/null
+++ b/src/runtime/testdata/testwinlib/main.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <windows.h>
+#include "testwinlib.h"
+
+int exceptionCount;
+int continueCount;
+LONG WINAPI customExceptionHandlder(struct _EXCEPTION_POINTERS *ExceptionInfo)
+{
+ if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
+ {
+ exceptionCount++;
+ // prepare context to resume execution
+ CONTEXT *c = ExceptionInfo->ContextRecord;
+ c->Rip = *(ULONG_PTR *)c->Rsp;
+ c->Rsp += 8;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+LONG WINAPI customContinueHandlder(struct _EXCEPTION_POINTERS *ExceptionInfo)
+{
+ if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
+ {
+ continueCount++;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+void throwFromC()
+{
+ DebugBreak();
+}
+int main()
+{
+ // simulate a "lazily" attached debugger, by calling some go code before attaching the exception/continue handler
+ Dummy();
+ exceptionCount = 0;
+ continueCount = 0;
+ void *exceptionHandlerHandle = AddVectoredExceptionHandler(0, customExceptionHandlder);
+ if (NULL == exceptionHandlerHandle)
+ {
+ printf("cannot add vectored exception handler\n");
+ return 2;
+ }
+ void *continueHandlerHandle = AddVectoredContinueHandler(0, customContinueHandlder);
+ if (NULL == continueHandlerHandle)
+ {
+ printf("cannot add vectored continue handler\n");
+ return 2;
+ }
+ CallMeBack(throwFromC);
+ RemoveVectoredContinueHandler(continueHandlerHandle);
+ RemoveVectoredExceptionHandler(exceptionHandlerHandle);
+ printf("exceptionCount: %d\ncontinueCount: %d\n", exceptionCount, continueCount);
+ return 0;
+} \ No newline at end of file
diff --git a/src/runtime/testdata/testwinlib/main.go b/src/runtime/testdata/testwinlib/main.go
new file mode 100644
index 0000000000..400eaa1c82
--- /dev/null
+++ b/src/runtime/testdata/testwinlib/main.go
@@ -0,0 +1,28 @@
+// +build windows,cgo
+
+package main
+
+// #include <windows.h>
+// typedef void(*callmeBackFunc)();
+// static void bridgeCallback(callmeBackFunc callback) {
+// callback();
+//}
+import "C"
+
+// CallMeBack call backs C code.
+//export CallMeBack
+func CallMeBack(callback C.callmeBackFunc) {
+ C.bridgeCallback(callback)
+}
+
+// Dummy is called by the C code before registering the exception/continue handlers simulating a debugger.
+// This makes sure that the Go runtime's lastcontinuehandler is reached before the C continue handler and thus,
+// validate that it does not crash the program before another handler could take an action.
+// The idea here is to reproduce what happens when you attach a debugger to a running program.
+// It also simulate the behavior of the .Net debugger, which register its exception/continue handlers lazily.
+//export Dummy
+func Dummy() int {
+ return 42
+}
+
+func main() {}