I would strongly advise avoiding unix-signals from CGO. I've done it and can recommend against it (it needs very elaborate signal masking to avoid crashing the Go runtime); it was still very fraught and probably not supported :)
Just catch C-side exceptions in C, turn them into strings, pass the string back to your Go stub, and send the string on a channel from Go to Go if you need to. On Sunday, January 19, 2025 at 1:58:51 PM UTC Robert Engels wrote: > After more reading, if you install the vectored exception handler it > should work as it can receive the exceptions outside its own stack frames. > > On Jan 19, 2025, at 7:47 AM, Robert Engels <ren...@ix.netcom.com> wrote: > > > > Read this section: Go handles the exceptions listed otherwise this is the > process: > > Raising an exception causes the exception dispatcher to go through the > following search for an exception handler: > > 1. The system first attempts to notify the process's debugger, if any. > 2. If the process is not being debugged, or if the associated debugger > does not handle the exception, the system attempts to locate a frame-based > exception handler by searching the stack frames of the thread in which the > exception occurred. The system searches the current stack frame first, > then > proceeds backward through preceding stack frames. > 3. If no frame-based handler can be found, or no frame-based handler > handles the exception, the system makes a second attempt to notify the > process's debugger. > 4. If the process is not being debugged, or if the associated debugger > does not handle the exception, the system provides default handling based > on the exception type. For most exceptions, the default action is to call > the ExitProcess > > <https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-exitprocess> > function. > > > > > On Jan 19, 2025, at 7:45 AM, Robert Engels <ren...@ix.netcom.com> wrote: > > > 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 <rudeusqu...@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? >> >> [image: go.png] >> >> go/src/syscall/types_windows.go at >> 40b3c0e58a0ae8dec4684a009bf3806769e0fc41 · golang/go >> <https://github.com/golang/go/blob/40b3c0e58a0ae8dec4684a009bf3806769e0fc41/src/syscall/types_windows.go#L54-L86> >> github.com >> <https://github.com/golang/go/blob/40b3c0e58a0ae8dec4684a009bf3806769e0fc41/src/syscall/types_windows.go#L54-L86> >> >> <https://github.com/golang/go/blob/40b3c0e58a0ae8dec4684a009bf3806769e0fc41/src/syscall/types_windows.go#L54-L86> >> >> >> On Jan 18, 2025, at 12:46 PM, rudeus greyrat <rudeusqu...@gmail.com> >> wrote: >> >> 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. >>> >>> On Jan 18, 2025, at 12:10 PM, rudeus greyrat <rudeusqu...@gmail.com> >>> wrote: >>> >>> 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) >>> >>> I might add this to my evil-go fork :p >>> https://github.com/almounah/evil-go >>> >>> 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. >>>> >>>> On Jan 18, 2025, at 8:06 AM, Robert Engels <ren...@ix.netcom.com> >>>> wrote: >>>> >>>> >>>> >>>> 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. >>>> >>>> On Jan 18, 2025, at 7:32 AM, Robert Engels <ren...@ix.netcom.com> >>>> wrote: >>>> >>>> >>>> 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.* >>>> >>>> On Jan 18, 2025, at 7:21 AM, rudeus greyrat <rudeusqu...@gmail.com> >>>> wrote: >>>> >>>> >>>> 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 : >>>>> >>>>>> >>>>>> https://stackoverflow.com/questions/79365198/cannot-continue-after-entering-vectored-exception-handler-in-go >>>>>> >>>>>> 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 >>>> >>>> <https://groups.google.com/d/msgid/golang-nuts/59818114-e21a-4b34-9f48-f6ff6e257c0fn%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>>> >>>> -- >>>> 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 >>>> >>>> <https://groups.google.com/d/msgid/golang-nuts/35174CC7-0301-4891-8D8F-EC3735AECA5A%40ix.netcom.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>>> >>>> -- >>>> 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/237A6F4C-29A1-423D-83B5-C4590C221424%40ix.netcom.com >>>> >>>> <https://groups.google.com/d/msgid/golang-nuts/237A6F4C-29A1-423D-83B5-C4590C221424%40ix.netcom.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>>> >>> -- >>> 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/d4bf1715-d073-49b6-ab67-27240a276f15n%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/d4bf1715-d073-49b6-ab67-27240a276f15n%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> >>> >> -- >> 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/507bfa72-5586-4030-9b5f-d71998169da2n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/507bfa72-5586-4030-9b5f-d71998169da2n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> >> -- > 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/81184ca4-8a10-4457-a366-ae01c45f8ce3n%40googlegroups.com > > <https://groups.google.com/d/msgid/golang-nuts/81184ca4-8a10-4457-a366-ae01c45f8ce3n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > -- > 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/20874169-5C6E-4947-978C-9E627CF3BA7A%40ix.netcom.com > > <https://groups.google.com/d/msgid/golang-nuts/20874169-5C6E-4947-978C-9E627CF3BA7A%40ix.netcom.com?utm_medium=email&utm_source=footer> > . > > -- > 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/8621A752-464F-465C-A7E1-003D05360939%40ix.netcom.com > > <https://groups.google.com/d/msgid/golang-nuts/8621A752-464F-465C-A7E1-003D05360939%40ix.netcom.com?utm_medium=email&utm_source=footer> > . > > -- 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/e7d063e4-33fe-4379-afe1-bef775a2e38dn%40googlegroups.com.