You need to install a handler using CGO. When it is not a Go exception it uses “continue” - eventually your handler will be called. You handle it in the native Go and communicate the signal back to Go using a channel of some other means.
A lot depends on what you are trying to do and why? Why not just use one of the “user defined” signals instead of the special one you are trying to use. Then you can use the standard signals package. On Jan 19, 2025, at 7:03 AM, rudeus greyrat <rudeusquagmir...@gmail.com> wrote:
I investigated a little bit and got lost :p
Basically I raise a windows exception with RaiseException windows API to simulate my exception (https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-raiseexception)
From what I understand, Go search the exception handler vector and because it is not a go exception (See https://github.com/golang/go/blob/40b3c0e58a0ae8dec4684a009bf3806769e0fc41/src/runtime/signal_windows.go#L310) it _EXCEPTION_CONTINUE_SEARCH then it is going to winthrow (https://github.com/golang/go/blob/40b3c0e58a0ae8dec4684a009bf3806769e0fc41/src/runtime/signal_windows.go#L349C1-L349C5) then printing the stack and exiting the program.
I don't see how it can be translated to a go signal ...
Le samedi 18 janvier 2025 à 20:20:27 UTC+1, robert engels a écrit :
Are you certain the exception isn’t already being translated to a signal?
I will try to do that later in CGO !!
If I remember correctly (tell me if I am wrong) The thing is I noticed when I compile with CGO the binary is much bigger ... So I avoid using CGO whenever it is possible and always try to rely on go assembler and go :) Le samedi 18 janvier 2025 à 19:28:13 UTC+1, robert engels a écrit :
Rather than modifying the Go runtime, why not install the exception handler using CGO, and then report back to go and fire the signal there using the signals package?
Although reading the signals package, https://pkg.go.dev/os/signal I would expect that this exception - since it is unrelated to running Go code - should be reported as one of the other OS signals. Thanks for answering. Basically I found a work around.
As I said, I understand go handles error differently, but imagine my windows OS send an exception signal not handled by go, how to handle this ? Escpecially given I don;'t just want the default Go handler that print the stack with the exception code and registers then exit the program ...
By default, in the Go runtime you indeed use the AddVectoredExceptionHandler windows API (which is why it is imported by Kernel32.dll in the Import Address Table and linked to the Go binary).
However you use just a set of exception and not everything :D
Correct me If I am wrong but from what I saw in `signal_windows.go`: ``` case _EXCEPTION_ACCESS_VIOLATION: case _EXCEPTION_IN_PAGE_ERROR: case _EXCEPTION_INT_DIVIDE_BY_ZERO: case _EXCEPTION_INT_OVERFLOW: case _EXCEPTION_FLT_DENORMAL_OPERAND: case _EXCEPTION_FLT_DIVIDE_BY_ZERO: case _EXCEPTION_FLT_INEXACT_RESULT: case _EXCEPTION_FLT_OVERFLOW: case _EXCEPTION_FLT_UNDERFLOW: case _EXCEPTION_BREAKPOINT: case _EXCEPTION_ILLEGAL_INSTRUCTION: // breakpoint arrives this way on arm64 ```
You only treat these exceptions in `isgoexception` function.
I changed `isgoexception` to:
``` func isgoexception(info *exceptionrecord, r *context) bool { switch info.exceptioncode { default: return false case _EXCEPTION_ACCESS_VIOLATION: case _EXCEPTION_IN_PAGE_ERROR: case _EXCEPTION_INT_DIVIDE_BY_ZERO: case _EXCEPTION_INT_OVERFLOW: case _EXCEPTION_FLT_DENORMAL_OPERAND: case _EXCEPTION_FLT_DIVIDE_BY_ZERO: case _EXCEPTION_FLT_INEXACT_RESULT: case _EXCEPTION_FLT_OVERFLOW: case _EXCEPTION_FLT_UNDERFLOW: case _EXCEPTION_BREAKPOINT: case 0xE0000001: // HERE I added this and changed order case _EXCEPTION_ILLEGAL_INSTRUCTION: // breakpoint arrives this way on arm64 } return true
if r.ip() < firstmoduledata.text || firstmoduledata.etext < r.ip() { println("In Weird Stuff") return false }
return true }
```
And basically I can now handle my Exception Signal.
``` func myHandler(exceptionInfo *handler.EXCEPTION_POINTERS) uintptr { println("Exception occurred! ---> Code") println(exceptionInfo.ExceptionRecord.ExceptionCode) println("Life happens, lets continue") // kernel32 := windows.NewLazySystemDLL("kernel32.dll") // exitt := kernel32.NewProc("ExitThread") // exitt.Call(uintptr(0)) return uintptr(handler.EXCEPTION_CONTINUE_EXECUTION) }
func main() { handler.AddVEH(myHandler)
raiseCustomException()
println("Continued") } ```
I get what I want when I run the exe:
``` Added VEH Exception occurred! ---> Code 3758096385 Life happens, lets continue Continued ```
I still not fully understand how you handle AddVectoredExceptionHandler in the go runtime and why Go decided not to let the user handle their signal ... (as you see it seems easy, escepcially when the signal is exterior to the go runtime)
PS: Don't take this the wrong way, but I hope "Generative AI is experimental" will stay experimental ...
Le samedi 18 janvier 2025 à 15:15:57 UTC+1, Robert Engels a écrit :
You may also want to look into ago “signal handling” as a potential solution.
If that wasn’t clear. It doesn’t seem to be supported. You need to catch the exception in the native code and return an error code back to Go. Go and C handle errors differently: - Go: Go uses error values returned from functions to handle errors. This approach makes error handling explicit and encourages developers to handle them gracefully.
- C: C often uses exceptions and signals to handle errors. However, C's error handling mechanisms don't directly translate to Go's error handling approach.
Handling Errors in CGO: - Return Values: Many C functions return error codes or status values. You can check these values in your Go code and handle them accordingly.
- errno: C often sets the global variable errno to indicate an error. You can access errno in Go using syscall.Errno.
- C++ Exceptions: C++ exceptions are not directly supported by CGO. If your C++ code throws exceptions, you can wrap the code in a C function that catches the exceptions and returns an error code.
Example: package main
/* #include <stdio.h> #include <stdlib.h>
int divide(int a, int b, int *result) { if (b == 0) { return -1; // Error: division by zero } *result = a / b; return 0; // Success } */ import "C" import ( "fmt" "syscall" )
func main() { var result C.int ret := C.divide(10, 0, &result) if ret != 0 { if ret == -1 { fmt.Println("Error: division by zero") } else { fmt.Println("Error:", syscall.Errno(-ret)) } } else { fmt.Println("Result:", int(result)) } }
|
Important Considerations: - Error Handling Consistency: Strive to maintain consistent error handling across your Go and C code.
- Panic: Avoid panicking in CGO code. Instead, return error values to your Go code to handle them gracefully.
- Memory Management: Be mindful of memory allocation and deallocation when working with CGO.
Alternatives to CGO: - Go Wrappers: If possible, consider writing pure Go wrappers around C libraries to provide a more idiomatic Go interface.
- RPC: For more complex interactions, consider using RPC mechanisms like gRPC to communicate between Go and C components.
Generative AI is experimental. The issue seems to come from firstcontinuehandler, I tweaked it a little and it is getting better
``` // It seems Windows searches ContinueHandler's list even // if ExceptionHandler returns EXCEPTION_CONTINUE_EXECUTION. // firstcontinuehandler will stop that search, // if exceptionhandler did the same earlier. // // It is nosplit for the same reason as exceptionhandler. // //go:nosplit func firstcontinuehandler(info *exceptionrecord, r *context, gp *g) int32 { print("Went in first Continue Handler") if !isgoexception(info, r) { println("It is not go exception") return _EXCEPTION_CONTINUE_SEARCH } println("It is a go exception") return _EXCEPTION_CONTINUE_EXECUTION } ```
Seems go is not allowing "non Go exception" to be handled by Go code
Le samedi 18 janvier 2025 à 12:51:12 UTC+1, rudeus greyrat a écrit :
Any idea please ? Been stuck at this for quite some time, seems that Go is neglecting the return uintptr(handler.EXCEPTION_CONTINUE_SEARCH) and going into panic mode ...
Le vendredi 17 janvier 2025 à 16:30:24 UTC+1, rudeus greyrat a écrit :
asked the question here too if people want to have syntax highlight
Le vendredi 17 janvier 2025 à 14:16:30 UTC+1, rudeus greyrat a écrit :
PS: I know there is defer recover mechanism in Go that can be used to handle exception... But I would like to use AddVectoredExceptionHandler (maybe it is already used behind the scene with defer recover ?) because I can inspect the thread context in myhandler function
Le vendredi 17 janvier 2025 à 13:17:07 UTC+1, rudeus greyrat a écrit :
I want to be able to catch windows exception and do stuff with it (mainly for hardware break point later).
I created a custom function to add a Vectored Exception Handler using the windows API call AddVectoredExceptionHandler: ```
func AddVEH(myHandler PVECTORED_EXCEPTION_HANDLER) error { kernel32 := syscall.NewLazyDLL("kernel32.dll") addVectoredExceptionHandler := kernel32.NewProc("AddVectoredExceptionHandler")
_, _, err := addVectoredExceptionHandler.Call( uintptr(1), syscall.NewCallback(func(exceptionInfo *EXCEPTION_POINTERS) uintptr { return myHandler(exceptionInfo) }), ) if err != nil { fmt.Println("Error Setting the VEH") fmt.Println(err.Error()) } return err } ```
I test it with a custom exception I raise: ``` func myHandler(exceptionInfo *handler.EXCEPTION_POINTERS) uintptr { println("Exception occurred! ---> Code") println(exceptionInfo.ExceptionRecord.ExceptionCode) println("It happends in life, lets continue") return ^uintptr(0) // EXCEPTION_CONTINUE_EXECUTION = -1 }
func main() { handler.AddVEH(myHandler)
raiseCustomException() // Just Raises a custom EXCEPTION with RaiseException winapi and code 0xE0000001
println("Continued") } ```
As I return with EXCEPTION_CONTINUE_EXECUTION, I expect that `println("Continued")` will be executed. However, it is not the case at all: ``` Error Setting the VEH The operation completed successfully. Exception occurred! ---> Code 3758096385 It happends in life, lets continue Exception 0xe0000001 0x7eb71d5fb17c 0x1b 0x7ffc54e4b699 PC=0x7ffc54e4b699
runtime.cgocall(0xf1dde0, 0xc000049b30) runtime/cgocall.go:167 +0x3e fp=0xc00006fe28 sp=0xc00006fdc0 pc=0xf10a7e syscall.SyscallN(0xc00001e410?, {0xc0000121c0?, 0x0?, 0xf39a00?}) ```
As you see the program enter the handler function but never continues, rather it exit and print the stack trace...
Not sure if it is because of syscall.NewCallback or something else ...
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/59818114-e21a-4b34-9f48-f6ff6e257c0fn%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/35174CC7-0301-4891-8D8F-EC3735AECA5A%40ix.netcom.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/81184ca4-8a10-4457-a366-ae01c45f8ce3n%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/20874169-5C6E-4947-978C-9E627CF3BA7A%40ix.netcom.com.
|