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+unsubscr...@googlegroups.com.
To view this discussion visit 
https://groups.google.com/d/msgid/golang-nuts/d4bf1715-d073-49b6-ab67-27240a276f15n%40googlegroups.com.

Reply via email to