Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: signal arrived during external code execution that calls setjmp on Windows #13672

Open
redstorm-fyy opened this issue Dec 18, 2015 · 32 comments
Labels
help wanted NeedsFix The path to resolution is known, but the work has not been done. OS-Windows
Milestone

Comments

@redstorm-fyy
Copy link

Processor Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz
OS: Windows 7 64
golang:1.5.2
gcc:mingw-w64 version 5.2.0 x86_64-posix-seh-rt_v4-rev1

When I compile golang with some external c code which using the setjmp and longjmp,the program crash.

My c code is here (It's in a c file in a directory which implements package lua)

#include <stdio.h>
#include <setjmp.h>
void Print(){
    jmp_buf c;
    if(setjmp(c)==0){
        longjmp(c,1);
    }
    else{
        printf("receive an exception\n");
    }
}

My go code

package main
import "github.com/redstorm-fyy/go-lua/lua"
func main() {
    lua.Print()
}

Important!
It crashes when the c code is in an external file.When the c code is just up the .go file's import "C",It does not crash.

Crash information
Exception 0xc0000028 0x0 0x0 0x77b096f8
PC=0x77b096f8
signal arrived during external code execution

github.com/redstorm-fyy/go-lua/lua._Cfunc_Print()
??:0 +0x38
github.com/redstorm-fyy/go-lua/lua.Print()
E:/GolangRoot/src/github.com/redstorm-fyy/go-lua/lua/luago.go:587 +0x1b
main.main()
E:/GolangRoot/src/github.com/redstorm-fyy/go-lua/example/exam.go:6 +0x1b

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
c:/go/src/runtime/asm_amd64.s:1721 +0x1
rax 0xf
rbx 0xc0000028
rcx 0x22ebd0
rdi 0x22c000
rsi 0x22f7b0
rbp 0x22f230
rsp 0x22eb10
r8 0x0
r9 0x400000
r10 0x0
r11 0x22f330
r12 0x22fe60
r13 0x22fdb0
r14 0x4013e8
r15 0x584024
rip 0x77b096f8
rflags 0x202
cs 0x33
fs 0x53
gs 0x2b

@ianlancetaylor
Copy link
Contributor

Looks a lot like #9754.

Any chance you can write a standalone test case that does not involve using Lua?

@ianlancetaylor ianlancetaylor changed the title signal arrived during external code execution cmd/cgo: signal arrived during external code execution Dec 18, 2015
@ianlancetaylor ianlancetaylor changed the title cmd/cgo: signal arrived during external code execution cmd/cgo: signal arrived during external code execution that calls setjmp on Windows Dec 18, 2015
@ianlancetaylor ianlancetaylor added this to the Go1.6Maybe milestone Dec 18, 2015
@minux
Copy link
Member

minux commented Dec 20, 2015

I assumed the OP meant this code:

package main
/*
#include <stdio.h>
#include <setjmp.h>
void Print() {
jmp_buf c;
if (setjmp(c) == 0)
longjmp(c,1);
else
printf("receive an exception\n");
}
*/
import "C"
func main() {
C.Print()
}

will panic on windows.

I tried to reproduce it on windows/amd64, external linking works,
but internal linker fails.

C:\go\src>..\bin\go run -ldflags "-linkmode internal" x.go
Exception 0xc0000005 0x8 0xfffffffff9058d48 0xfffffffff9058d48
PC=0xfffffffff9058d48
signal arrived during external code execution

main._Cfunc_Print()
command-line-arguments/_obj/_cgo_gotypes.go:43 +0x38
main.main()
x.go:19 +0x1b

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
C:/go/src/runtime/asm_amd64.s:1998 +0x1

rax 0x459466
rbx 0xc082027f38
rcx 0x22fdd0
rdi 0xc082027f38
rsi 0x4c4c00
rbp 0x22fed0
rsp 0x22fda8
r8 0x45941a
r9 0xc082027ee0
r10 0x11
r11 0x0
r12 0x5
r13 0x4957a5
r14 0x1
r15 0x8
rip 0xfffffffff9058d48
rflags 0x10246
cs 0x33
fs 0x53
gs 0x2b
exit status 2

I'm not convinced that we need to fix internal linking as external linking
is the default now.

@ianlancetaylor
Copy link
Contributor

If I'm reading this right, the problem is that cmd/link is not generating the correct exception information for the Windows OS. Is that correct?

@minux
Copy link
Member

minux commented Dec 21, 2015 via email

@ianlancetaylor
Copy link
Contributor

It seems pretty clear from the error message that some exception is occurring.

This MSDN page implies that longjmp is exception aware: https://msdn.microsoft.com/en-us/library/yz2ez4as.aspx .

@minux
Copy link
Member

minux commented Dec 21, 2015 via email

@rsc
Copy link
Contributor

rsc commented Jan 14, 2016

cmd/link/internal/amd64/asm.go seems to want to reject this case:

case 256 + ld.R_X86_64_PC32:
    if targ.Type == obj.SDYNIMPORT {
        ld.Diag("unexpected R_X86_64_PC32 relocation for dynamic symbol %s", targ.Name)
    }
    if targ.Type == 0 || targ.Type == obj.SXREF {
        ld.Diag("unknown symbol %s in pcrel", targ.Name)
    }
    r.Type = obj.R_PCREL
    r.Add += 4
    return

But this only applies to the symbols that the linker knows are being imported. I believe here the generated .o file has inside it a reference to __imp_longjmp, and the linker knows nothing about that, and in particular does not have it marked as SDYNIMPORT, so no error is produced.

I don't believe the linker is set up to handle this case. It's not just a trivial fix. Given that, we should probably leave this for Go 1.7.

@rsc rsc modified the milestones: Go1.7Early, Go1.6Maybe Jan 14, 2016
@alexbrainman
Copy link
Member

I did some debuging here:

diff --git a/src/cmd/link/internal/ld/ldpe.go b/src/cmd/link/internal/ld/ldpe.go
index 8439c06..d8788c9 100644
--- a/src/cmd/link/internal/ld/ldpe.go
+++ b/src/cmd/link/internal/ld/ldpe.go
@@ -128,6 +128,8 @@ type PeObj struct {
 }

 func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
+   fmt.Printf("\nprocessing file %s\n\n", pn)
+   defer fmt.Printf("\ndone with %s\n", pn)
    if Debug['v'] != 0 {
        fmt.Fprintf(&Bso, "%5.2f ldpe %s\n", obj.Cputime(), pn)
    }
@@ -199,6 +201,7 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
    // read symbols
    peobj.pesym = make([]PeSym, peobj.fh.NumberOfSymbols)

+   fmt.Printf("\npe symbols for %v:\n", pn)
    peobj.npesym = uint(peobj.fh.NumberOfSymbols)
    obj.Bseek(f, int64(base)+int64(peobj.fh.PointerToSymbolTable), 0)
    for i := 0; uint32(i) < peobj.fh.NumberOfSymbols; i += numaux + 1 {
@@ -223,6 +226,9 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
        if numaux < 0 {
            numaux = 0
        }
+       if strings.Contains(pn, "issue13672.a") {
+           fmt.Printf("%d: %v\t\tsection=%d value=0x%x\n", i, peobj.pesym[i].name, peobj.pesym[i].sectnum, peobj.pesym[i].value)
+       }
    }

    // create symbols for mapped sections
@@ -287,6 +293,7 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
            continue
        }

+       fmt.Printf("\npe relocations for section %v:\n", rsect.name)
        r = make([]Reloc, rsect.sh.NumberOfRelocations)
        obj.Bseek(f, int64(peobj.base)+int64(rsect.sh.PointerToRelocations), 0)
        for j = 0; j < int(rsect.sh.NumberOfRelocations); j++ {
@@ -297,6 +304,10 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
            rva := Le32(symbuf[0:])
            symindex := Le32(symbuf[4:])
            type_ := Le16(symbuf[8:])
+           if rsect.name == ".text" && strings.Contains(pn, "issue13672.a") {
+               fmt.Printf("%d: type=%v rva=0x%x symindex=%v\n", j, type_, rva, symindex)
+           }
+
            if err = readpesym(peobj, int(symindex), &sym); err != nil {
                goto bad
            }
@@ -348,6 +359,13 @@ func ldpe(f *obj.Biobuf, pkg string, length int64, pn string) {
        s = rsect.sym
        s.R = r
        s.R = s.R[:rsect.sh.NumberOfRelocations]
+
+       if rsect.name == ".text" && strings.Contains(pn, "issue13672.a") {
+           fmt.Printf("\ngo relocations for section %v:\n", s.Name)
+           for i, r := range s.R {
+               fmt.Printf("%d: Off=0x%x Sym(addr=%p name=%s type=%d dynimplib=%s extname=%s value=0x%x size=0x%x)\n", i, r.Off, r.Sym, r.Sym.Name, r.Sym.Type, r.Sym.Dynimplib, r.Sym.Extname, r.Sym.Value, r.Sym.Size)
+           }
+       }
    }

    // enter sub-symbols into symbol table.

and I get this output

C:\dev\src\issues\issue13672>go build -ldflags="-linkmode=internal"
# issues/issue13672

processing file $WORK\issues\issue13672.a(_all.o)


pe symbols for $WORK\issues\issue13672.a(_all.o):
0: .file        section=65534 value=0x12
2: .text        section=1 value=0x0
4: .data        section=3 value=0x0
6: .bss     section=8 value=0x0
8: .debug_info      section=10 value=0x0
10: .debug_abbrev       section=11 value=0x0
12: .debug_aranges      section=9 value=0x0
14: .debug_line     section=12 value=0x0
16: .rdata$zzz      section=5 value=0x20
18: .file       section=65534 value=0x31
20: Print       section=1 value=0x0
22: _cgo_7d1619ce4bb5_Cfunc_Print       section=1 value=0x50
23: .text       section=1 value=0x0
25: .data       section=3 value=0x0
27: .bss        section=8 value=0x0
29: .rdata      section=4 value=0x0
31: .xdata      section=7 value=0x0
33: .pdata      section=6 value=0x0
35: .debug_info     section=10 value=0x18f
37: .debug_abbrev       section=11 value=0x19
39: .debug_loc      section=15 value=0x0
41: .debug_aranges      section=9 value=0x20
43: .debug_line     section=12 value=0x1d
45: .rdata$zzz      section=5 value=0x0
47: .debug_frame        section=13 value=0x0
49: .file       section=65534 value=0x44
51: mingw_getsp     section=1 value=0x60
53: longjmp     section=1 value=0x66
54: .debug_info     section=10 value=0x4e5
56: .debug_abbrev       section=11 value=0x16c
58: .debug_line     section=12 value=0xc8
60: .text       section=1 value=0x60
62: .data       section=3 value=0x0
64: .bss        section=8 value=0x0
66: .debug_aranges      section=9 value=0x50
68: __imp_longjmp       section=0 value=0x0
69: puts        section=0 value=0x0
70: _setjmp     section=0 value=0x0

pe relocations for section .text:
0: type=4 rva=0x16 symindex=70
1: type=4 rva=0x21 symindex=29
2: type=4 rva=0x26 symindex=69
3: type=4 rva=0x41 symindex=53
4: type=4 rva=0x69 symindex=68

go relocations for section main(.text):
0: Off=0x16 Sym(addr=0xc0820697a0 name=_setjmp type=41 dynimplib=msvcrt.dll extname=_setjmp value=0x0 size=0x0)
1: Off=0x21 Sym(addr=0xc082f190e0 name=main(.rdata) type=8 dynimplib= extname=main(.rdata) value=0x0 size=0x20)
2: Off=0x26 Sym(addr=0xc0820705a0 name=puts type=41 dynimplib=msvcrt.dll extname=puts value=0x0 size=0x0)
3: Off=0x41 Sym(addr=0xc082070240 name=longjmp type=41 dynimplib=msvcrt.dll extname=longjmp value=0x0 size=0x0)
4: Off=0x69 Sym(addr=0xc082070240 name=longjmp type=41 dynimplib=msvcrt.dll extname=longjmp value=0x0 size=0x0)

pe relocations for section .pdata:

done with $WORK\issues\issue13672.a(_all.o)

processing file C:\dev\go/pkg/windows_amd64/runtime/cgo.a(_all.o)


pe symbols for C:\dev\go/pkg/windows_amd64/runtime/cgo.a(_all.o):

pe relocations for section .text:

pe relocations for section .pdata:

done with C:\dev\go/pkg/windows_amd64/runtime/cgo.a(_all.o)

Note that _all.o .text section has two interesting pe relocations: 3 and 4. 3 has symindex=53 which points to symbol

53: longjmp     section=1 value=0x66

that points to small longjmp function in .text. While 4 has symindex=68 which points to symbol

68: __imp_longjmp       section=0 value=0x0

which is just a place for external function (longjmp that gcc hoping to find in msvcrt.dll).

You can also see those relocations converted into "go relocations". But "go relocatoins" 3 and 4 points to the same symbol. And this symbol settings match neither original longjmp nor __imp_longjmp settings. So I am not surprised that linker generates invalid code here.

I think this is all to do with symbol renaming we do in readpesym.

Alex

@actgardner
Copy link

I'm experiencing the same issue with the external linker - I was able to reproduce the issue as redstorm described it: when Print() is defined in an external C file, the longjmp() call results in a stack trace.

It's a bit tough to follow here: are there any leads on why externally linked binaries would still have this issue?

@actgardner
Copy link

@redstorm-fyy If this is still impacting you, I was able to work around it by using __builtin_setjmp and __builtin_longjmp. They aren't affected by this issue. This appears to be a MinGW bug on 64-bit platforms: https://sourceforge.net/p/mingw-w64/bugs/406/

@bradfitz bradfitz modified the milestones: Go1.7Maybe, Go1.7Early May 5, 2016
@rsc rsc modified the milestones: Go1.8, Go1.7Maybe May 17, 2016
@quentinmit quentinmit added the NeedsFix The path to resolution is known, but the work has not been done. label Oct 5, 2016
@rsc rsc modified the milestones: Go1.9Early, Go1.8 Oct 21, 2016
@bradfitz bradfitz modified the milestones: Go1.9Maybe, Go1.9Early May 3, 2017
@bradfitz bradfitz added this to the Go1.10 milestone Jul 20, 2017
@BorisKozo
Copy link

BorisKozo commented Jul 20, 2017

I am on
go version go1.8.1 windows/amd64
I am writing a simple unit test against sqlite3 driver compiled in CGo.
My unit test opens a DB, and closes it (does nothing on the DB)
I am building with the flags -i -ldflags="-linkmode internal" via Gogland (JetBrains) because otherwise the debugger fails with another error.

When I call db.Close() (I verified there is an open connection) I get the following:

Exception 0xc0000005 0x8 0xaa92f8 0xaa92f8
PC=0xaa92f8
signal arrived during external code execution

github.com/mattn/go-sqlite3._Cfunc_sqlite3_close_v2(0x10f7018, 0x0)
	github.com/mattn/go-sqlite3/_obj/_cgo_gotypes.go:495 +0x50
github.com/mattn/go-sqlite3.(*SQLiteConn).Close.func1(0x10f7018, 0x0)
	C:/projects/Phoenix/go/src/github.com/mattn/go-sqlite3/sqlite3.go:759 +0x67
github.com/mattn/go-sqlite3.(*SQLiteConn).Close(0xc04215c960, 0x69e53e, 0xc04219dce8)
	C:/projects/Phoenix/go/src/github.com/mattn/go-sqlite3/sqlite3.go:759 +0x3a
database/sql.(*driverConn).finalClose.func2()
	C:/Go/src/database/sql/sql.go:440 +0x50
database/sql.withLock(0xaad500, 0xc04216e3f0, 0xc04219dd60)
	C:/Go/src/database/sql/sql.go:2545 +0x6c
database/sql.(*driverConn).finalClose(0xc04216e3f0, 0xc04219de78, 0x4219de70)
	C:/Go/src/database/sql/sql.go:442 +0x160
database/sql.(finalCloser).(database/sql.finalClose)-fm(0xc04216a348, 0xc0420d0cf0)
	C:/Go/src/database/sql/sql.go:537 +0x36
database/sql.(*DB).Close(0xc04216a320, 0xc04215e000, 0xc04219df00)
	C:/Go/src/database/sql/sql.go:644 +0x304
<project name>/DataMonitor.(*Database).Finalize(0xc04219df58, 0x0, 0x0)
	<project name>/db_wrapper.go:78 +0x36
<project name>/DataMonitor.TestDatabase_Initialize(0xc0421589c0)
	<project name>/db_wrapper_test.go:26 +0x1d0
testing.tRunner(0xc0421589c0, 0x8e4858)
	C:/Go/src/testing/testing.go:657 +0x9d
created by testing.(*T).Run
	C:/Go/src/testing/testing.go:697 +0x2d1

@bradfitz bradfitz removed the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Jul 20, 2017
@bradfitz
Copy link
Contributor

/cc @aclements

@aclements
Copy link
Member

@BorisKozo, it's not obvious to me that your crash involves setjmp/longjmp. Do you have evidence that it does? Basically anything going wrong in C code will cause "signal arrived during external code execution", and the exception code you got (0xc0000005, access violation) is different from the original report (0xc0000028, bad stack). Based on the exception code you got, it looks like the SQLite3 C code attempted to jump to a bad program counter (0xaa92f8).

@BorisKozo
Copy link

@aclements No evidence whatsoever. This is the first time I am doing something with CGo so I am not sure how to read those error messages or what they mean.

@redstorm-fyy
Copy link
Author

@bradfitz
This problem is still exist in go 1.8 windows/amd64
To solve the problem,I move the c code to the .go file.
The following code is ok.
As @alanctgardner said,this is the external linker's bug.

package main
/*
#include <stdio.h>
#include <setjmp.h>
void Print(){
printf("begin\n");
jmp_buf c;
if(setjmp(c)==0){
longjmp(c,1);
}
else{
printf("receive an exception\n");
}
printf("end\n");
}
*/
import "C"

func main(){
C.Print()
}

@alexbrainman
Copy link
Member

Is there still a problem here? @redstorm-fyy, @alexbrainman ?

Nothing changed since #13672 (comment)

This works with external linker, but broken with internal linker.

c:\Users\Alex\dev\src\issue\go\13672>go version
go version devel +16422078ab Thu Aug 3 04:24:28 2017 +0000 windows/amd64

c:\Users\Alex\dev\src\issue\go\13672>gcc --version
gcc (GCC) 4.9.1
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


c:\Users\Alex\dev\src\issue\go\13672>type main.go
package main

/*
#include <stdio.h>
#include <setjmp.h>
void Print() {
jmp_buf c;
if (setjmp(c) == 0)
longjmp(c,1);
else
printf("receive an exception\n");
}
*/
import "C"

func main() {
        C.Print()
}

c:\Users\Alex\dev\src\issue\go\13672>go run main.go
receive an exception

c:\Users\Alex\dev\src\issue\go\13672>go run -ldflags "-linkmode internal" main.go
Exception 0xc0000028 0x3100000200 0xff 0x7ff965564b90
PC=0x7ff965564b90
signal arrived during external code execution

main._Cfunc_Print()
        command-line-arguments/_obj/_cgo_gotypes.go:41 +0x48
main.main()
        c:/Users/Alex/dev/src/issue/go/13672/main.go:17 +0x27
rax     0x0
rbx     0xc0000028
rcx     0x0
rdi     0x7ff962dc61dc
rsi     0x6df320
rbp     0x6decb0
rsp     0x6debb0
r8      0x0
r9      0x0
r10     0x0
r11     0x76b8b2da85fb
r12     0x7ff962d40000
r13     0x7ff962d52774
r14     0x6dff48
r15     0x14
rip     0x7ff965564b90
rflags  0x202
cs      0x33
fs      0x53
gs      0x2b
exit status 2

c:\Users\Alex\dev\src\issue\go\13672>

I doubt many people use internal linker nowadays.
But I will try to investigate this again when I have time.

Alex

@ianlancetaylor
Copy link
Contributor

Reopening because the problem still exists.

@ianlancetaylor ianlancetaylor reopened this Aug 4, 2017
@rsc rsc modified the milestones: Go1.10, Go1.11 Nov 22, 2017
@spieglt
Copy link

spieglt commented Dec 7, 2017

Would this also be happening when using a DLL built with Visual Studio via the Syscall package? I believe I'm having similar symptoms.

@alexbrainman
Copy link
Member

Would this also be happening when using a DLL built with Visual Studio via the Syscall package?

The problem discussed in this issue can only happens with Go program that uses Cgo. If your program does not uses Cgo, it cannot have this problem.

Alex

@deadprogram
Copy link

Here is an example of what appears to be this same issue happening in a recent PR to GoCV: https://ci.appveyor.com/project/deadprogram/gocv/build/216#L141

This code works as expected on Linux, but fails same test on Windows using Go 1.9.2, seemingly for attempting to catch the exception:
https://github.com/hybridgroup/gocv/pull/55/files#diff-32d3fe6df51960dca7c273d37844190fR24

@ianlancetaylor
Copy link
Contributor

@deadprogram I suspect that that problem you mention is actually #12516. Doesn't help much as that one is not fixed either.

@deadprogram
Copy link

Hi @ianlancetaylor thanks for the tip. I will try out and exception handler that does not allocate any new memory and see if that helps.

@theAkito
Copy link

theAkito commented Feb 16, 2018

2 years and still no fix?

@mattn
Copy link
Member

mattn commented Feb 16, 2018

I tested this on Windows10 64bit.

setjmp

Does not reproduce.

@ianlancetaylor
Copy link
Contributor

@mattn As far as I know the bug only occurs when you explicitly use the internal linker via -ldflags=-linkmode=internal.

@Akito13 Why do you want to use the internal linker for code like this?

@mattn
Copy link
Member

mattn commented Feb 17, 2018

Sorry, I could reproduce it.

@jonatino
Copy link

jonatino commented Aug 23, 2020

PC=0x7ffdcbad041c
signal arrived during external code execution

syscall.Syscall(0x7ffdcbad0620, 0x3, 0x10003, 0x1, 0xc0007d7fe0, 0x0, 0x0, 0x0)
	C:/Go/src/runtime/syscall_windows.go:188 +0xe9
main.GetPhysicalMonitorsFromHMONITOR(0x10003, 0x1, 0xc0007d7fe0, 0x1)
	E:/Sync/Projects/Go/SmartDeck/windows.go:93 +0x6c
main.HookScreenBrightness()
	E:/Sync/Projects/Go/SmartDeck/windows.go:188 +0x164
created by main.main
	E:/Sync/Projects/Go/SmartDeck/SmartDeck.go:23 +0x58
func GetPhysicalMonitorsFromHMONITOR(handle syscall.Handle, monitorArraySize uint, array *[1]PhysicalMonitor) (result uintptr) {
	ret, _, callErr := syscall.Syscall(
		getPhysicalMonitorsFromHMONITOR,
		3,
		uintptr(handle),
		uintptr(monitorArraySize), uintptr(unsafe.Pointer(array)))

	if callErr != 0 {
		fmt.Println(callErr)
	}

	result = ret
	return
}

@htimli
Copy link

htimli commented Aug 11, 2021

I get the same error message (signal arrived during external code execution) when running the tracking sample.

Processor : Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz 1.19 GHz
OS : Windows 10 64 version 20H2
golang : go1.16.4
gcc : mingw-w64 version-7.2.0 x86_64--posix-seh-rt_v5-rev1
compiled with cmake 3.21.1
DLLs location was added to PATH

When I verify the installation of gocv by runing the example cmd\version\main.go
The version program output the following:
gocv version: 0.28.0
opencv lib version: 4.5.3

While when i try to run the example in cmd\hello\main.go who is supposed to open a video capture device using device “0”, read
frames, and show the video in a GUI window the program crash and I end up with this error :

Exception 0x20474343 0x1e75b12bef0 0x64945198 0x7ffcd8744ed9
PC=0x7ffcd8744ed9
signal arrived during external code execution

gocv.io/x/gocv._Cfunc_Window_IMShow(0x1e75b126a60, 0x1e75b12bce0)
_cgo_gotypes.go:7478 +0x45
gocv.io/x/gocv.(*Window).IMShow.func2(0x1e75b126a60, 0x1e75b12bce0, 0x0, 0x0, 0x0)
c:/Users/timli/gopath/src/gocv.io/x/gocv/highgui.go:158 +0x5e
gocv.io/x/gocv.(*Window).IMShow(0xc00019a060, 0x1e75b12bce0, 0x0, 0x0, 0x0)
c:/Users/timli/gopath/src/gocv.io/x/gocv/highgui.go:158 +0xab
main.main()
c:/Users/timli/gopath/src/gocv.io/x/gocv/cmd/hello/main.go:14 +0xdf
rax 0x4013e0100005804
rbx 0x1e75b12bef0
rcx 0x1e75b12bc20
rdi 0x1e75b12bf30
rsi 0x681f6770
rbp 0x1e75b12bf70
rsp 0x17b6bfef50
r8 0x7ffcdae5b90b
r9 0x50039
r10 0xd0
r11 0x1e75af850e0
r12 0x1e75b12bf90
r13 0x1
r14 0x17b6bff2e0
r15 0xffffffffffffffff
rip 0x7ffcd8744ed9
rflags 0x206
cs 0x33
fs 0x53
gs 0x2b

I'd like to add that I tried to run the same code in python with opencv (same camera id = 0 ) and it works well.

@qmuntal
Copy link
Contributor

qmuntal commented Jan 24, 2023

I've dug a little bit into this. The problem seems to be that on Windows, longjump internally uses Structured Exception Unwinding (SEH) to restore the stack to the previously saved point marked by setjump, but the Go internal linker does not preserve the SEH information stored by the C/C++ compiler. If the function containing the longjump does not have SEH information (which comes in the .pdata and .xdata section of the PE binary), then the unwinding process is unpredictable, and in the best case it will throw an exception once it reaches the top of the stack.

This is a longjmp Microsoft-specific behavior documented in its docs:

In Microsoft C++ code on Windows, longjmp uses the same stack-unwinding semantics as exception-handling code.

If my diagnostic is accurate, I might be able to fix this issue as part of #57302.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted NeedsFix The path to resolution is known, but the work has not been done. OS-Windows
Projects
None yet
Development

No branches or pull requests