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
runtime/cgo: calling DLL's export function crashes on Windows #9457
Comments
Do not have VS2013 to try it. Alex |
@alexbrainman You can use the execute file. https://www.dropbox.com/s/3rnan6sf1killge/GoDll_Binary.zip?dl=0 |
Thank you for DLL. Unfortunately I don't see anything new. Your DLL raises 0xC00000FD EXCEPTION_STACK_OVERFLOW. I don't know why - I don't understand your C++ code. Maybe it needs more stack space. Go is using 64K for its threads stack. Maybe that is not enough. You can try and change your program so that it uses cgo. Programs built with cgo reserve more stack space: 1M for 386 and 2M for amd64. Just to see if that solves your problem. I don't see how we can help you here. So closing this issue. Feel free to comment. Alex |
@alexbrainman If you just run the test.exe, everything is OK! Because the test.exe is compile by vs2013, it's written by C++. But, if you use go build with the file that godll.go and run it, you can got the exception。 |
Like I said earlier. Go decide how large thread stacks are. 64K is enough for Go. Obviously not enough for your DLL. I suspect your test.exe creates threads with bigger stacks. Alex |
I think i understand the underlying problem now. https://go.googlesource.com/go/+/master/src/cmd/ld/pe.c#685 We disabled the automatic stack expansion for the threads in the |
@alexbrainman If there is a dll that export function that need more than 64K stack size, and It's written by third party partner, I use go's syscall indirectly call it, It just crash. But it can work ok with C/C++. So Is it still not a problem? Before I add the Issue, I have talked with @minux , as @minux said, When I use syscall to call export function, the stack will use the system thread's stack. If so, there must be OK. |
@minux The test code just use 4 * 64K size. It's not exceed the default stack size 1MB on windows/386 or 2MB for windows/amd64 |
Aha, I think I found the culprit. Look at the code I quoted in last comment, if the code is not using cgo However, although using syscall to call external DLLs use the same I think just adding a blank import of "runtime/cgo" will fix your program. I'm not sure what to do here. |
Holy shit! Just add a blank import of "runtime/cgo", It works OK.... |
If the linker doesn't find "runtime/cgo" being imported, it will treat the This is yet another subtle difference between using cgo to call DLL I don't know anything that we could do here, so I guess we should just live |
No one else complained about this yet, so I don't think it is big problem. But I think we could increase stack size. As far as I remember we needed to have as many threads as possible in the early Go days. Our net package didn't use IOCP back then, so we had to use separate threads for different connections. windows/386 was our only platform so we could only have 2000 threads if their stack was 1M. I don't think this is an issue any more, especially on windows/amd64. Perhaps we could increase stacks now, but by how much? Perhaps I forget something else. But, I am sure, if we change stack sizes we will discover it :-) Alex |
My only concerns for increasing the stack limit is that it might reduce the I think we can increase the reserved stack value without such concerns? |
Yes increasing stack limit will reduce the maximum number of OS threads. This is for reserved stack value. We have small reserved stacks to allow for more threads. Windows would not commit all reserved stacks until they are actually read/written from/to. |
Actually, from my experiments, it seems windows doesn't fully commit the Moreover, the stack limit in PE header only affects the main thread, and As long as we don't use much stack space, I don't think increasing the size |
My test program looks like this: package main /* __stdcall void var n = flag.Int("n", 500, "number of threads to create") func main() { No matter the stack reservation size (64KB or 1MB), the maximum number of Do you spot any problems in this test? |
Re your test program http://play.golang.org/p/p_STYyr-qY Why does it use cgo? I though we're discussing/changing non-cgo scenario.. |
There is a typo in my test program (I named the test function "do"). |
Can you, please answer my question above. |
I created another test using dll + syscall, but the result is the same, thrs.c: http://play.golang.org/p/IRoFkJ871l To build: To run |
some of the discussion is on the CL: https://golang.org/cl/2237 @alexbrainman used http://play.golang.org/p/TKkNSAVYnw to prove that on 64-bit system, However, it seems that even without the CL, my Windows XP VM is allocating 1MB stack |
Running http://play.golang.org/p/TKkNSAVYnw on my 32-bit windows xp: C:\go\path\mine\src\foo>go run main.go 2> NUL C:\go\path\mine\src\foo> but after Change 2237 is applied: C:\go\path\mine\src\foo>go run main.go 2> NUL C:\go\path\mine\src\foo> So I can see about 8 times less threads after the change. Considering we made mistake about current threads are 64K - they are actually 128K except first thread (see runtime.newosproc), my results fit my understanding of this situation perfectly. @minux I am not sure why your threads are bigger. Perhaps your system is configured in a particular way. I am running stock standard windows xp system on real hardware. What does http://play.golang.org/p/TKkNSAVYnw print ono your system (on Go tip)? Alex |
I did some more experiments, here is the result: It seems the culprit is the stack commit size in PE header, if I lower it After this CL, i can only create 1233 threads, as expected. |
The stack reservation size is rounded to multiples of 64KB, so Update: in my last comment, I did modify the stack reservation in I will just update my CL to set the stack commit size to 4KB. And I will close this issue as unfortunate, the workaround is still to |
btw, all.bat still passes after reducing the stack size to 64KB, but |
Close as unfortunate. Workarounds:
|
CL https://golang.org/cl/2237 mentions this issue. |
…ntime With 128KB stack reservation, on 32-bit Windows, the maximum number threads is ~9000. The original 65535-byte stack commit is causing problem on Windows XP where it makes the stack reservation to be 1MB despite the fact that the runtime specified 128KB. While we're at here, also fix the extra spacings in the unable to create more OS thread error message: println will insert a space between each argument. See golang#9457 for more information. Change-Id: I3a82f7d9717d3d55211b6eb1c34b00b0eaad83ed Reviewed-on: https://go-review.googlesource.com/2237 Reviewed-by: Alex Brainman <alex.brainman@gmail.com> Run-TryBot: Minux Ma <minux@golang.org>
go1.4 windows amd64
OS: Windows 7 sp1 64Bit
I write a dll that exports some function. then I invoke these function in go through syscall. But it crashed. The error:
Exception 0xc00000fd 0x1 0x33000 0x7fef5017237
PC=0x7fef5017237
signal arrived during cgo execution
syscall.(_Proc).Call(0xc082004620, 0xc082049f58, 0x2, 0x2, 0xc, 0xc0820045c0, 0x0, 0x0)
c:/go/src/syscall/dll_windows.go:132 +0x36e
syscall.(_LazyProc).Call(0xc082007d40, 0xc082049f58, 0x2, 0x2, 0x4ff330, 0xc, 0x0, 0x0)
c:/go/src/syscall/dll_windows.go:279 +0x74
main.main()
D:/GoDll/godll.go:27 +0x1a1
rax 0x40370
rbx 0xc082049da8
rcx 0xc0820045a0
rdx 0xc0820045c0
rdi 0x7fffffde000
rsi 0xc082049e00
rbp 0x57ab00
rsp 0x6fe08
r8 0x0
r9 0xc082007d40
r10 0x2f000
r11 0x33000
r12 0x9
r13 0x0
r14 0x0
r15 0x0
rip 0x7fef5017237
rflags 0x7fe00010287
cs 0x33
fs 0x53
gs 0x2b
When I change the local variable that in Dll from stack to heap, the crash is disappeared, the result is correct.
The test code is at here: https://www.dropbox.com/s/ggxpmey59zex4lg/GoDll.zip?dl=0
If you haven't visual studio, you can download the execute files: https://www.dropbox.com/s/3rnan6sf1killge/GoDll_Binary.zip?dl=0
You can use VS2013 compile this.
The text was updated successfully, but these errors were encountered: