Euphoria
Ticket #462:
MinGW crashes when using normal callc
-
Reported by
jimcbrown
Nov 30, 2010
This was previously discovered before the RC1 release. Something is wrong with the callc code and MinGW that is causing it to crash whenever a C routine is called with call_c().
This is worked around by using the C-only version of call_c() in RC1 and later when eu.a is compiled with MinGW. As a result, c_func/c_proc now works under MinGW, and this is not an urgent bug (and can be safely postponed past 4.1.0 if necessary). Still, someone at somepoint should look into why this broke.
Details
1. Comment by mattlewis
Nov 30, 2010
The next debugging step is to try running objdump on be_runtime.c to look at the ASM of the callback routines.
2. Comment by jimcbrown
Nov 30, 2010
As of svn:3870 the callback code was working perfectly on MinGW ... has it since broke?
It's funny, that the more obscure callback code worked but the simpler asm-based call_c() is broke on MinGW.
3. Comment by jimcbrown
Dec 01, 2010
Assigning to eumario.
4. Comment by eumario
Dec 04, 2010
Do we have a test for this issue, that I can run and check to see if it is working or not?
5. Comment by jimcbrown
Dec 04, 2010
Line 83 of be_callc.c, change "#ifndef EMINGW" to "#if 1" or something, then rebuild mingw and run the callc.ex demo.
Or, t_dep.e and t_legacy_callback.e will expose the bug also.
6. Comment by eumario
Dec 05, 2010
Confirmed Fixed in Revision 4523, asm based call_c() is now properly working.
7. Comment by jimcbrown
Dec 05, 2010
I wonder what changed between svn:3810 and svn:4523 that fixed it.
8. Comment by ne1uno
Dec 06, 2010
I noticed a problem when the minGW built eui r4523+ will exit silently if you don't add a '+' in the function signature for calls to a routine in a compiled dll.
not sure what the correct behavior is here, but it seems wrong that eui would just exit w/o error.
I've uploaded some sample code with prebuilt dll's gcc4.5
ccheckdll.zip
to rebuild you would need qmake, available on many systems. or from http://qt.nokia.com as part of Qt GUI toolkit.
9. Comment by jimcbrown
Dec 06, 2010
Reopening, based on ne1uno's bug report.
10. Comment by SDPringle
Jun 29, 2011
I have been doing some research on this. I found out about GCC using a different calling convention than what is normal for Windows: CDECL and STDCALL, respectively. What happens if you open a mingw library? Does MINGW follow Windows calling conventions?
What if you actually need to use STDCALL on UNIX? You cannot.
The supplied test seems to work 100% no matter how many times I run it. Perhaps this was since fixed again or perhaps this is a problem in the main-trunk only?
11. Comment by SDPringle
Jun 29, 2011
This is working in eui version 77e6b084b433 (4.1 ARM branch)
12. Comment by mattlewis
Jun 30, 2011
I've never heard of gcc using a different calling convention on x86. Watcom and MSVC++ both have their own conventions (fastcall and thiscall, respectively, that I'm aware of). On Unix x86, there is only cdecl. x86-64 has its own convention that appears to be the same across windows and unix.
13. Comment by SDPringle
Jun 30, 2011
Don't misconstrue what I said. I said gcc's convention is different from what is normal on Windows.
14. Comment by mattlewis
Jun 30, 2011
The default convention on windows compilers is not actually STDCALL, which is why all of the windows headers have to declare it everywhere. For watcom, it's their fastcall, and for MSVC, it's CDECL. Outside of Pascal, I'm not aware of compilers that default to STDCALL.
15. Comment by SDPringle
Jun 30, 2011
For this ticket, the relevant to this ticket is the calling convention used in shared libraries.
CDECL : LUNIX and LINUX like OS libraries
STDCALL : WINDOWS
So, this code has the variables named badly.
ifdef WINDOWS then
constant libdll = open_dll("ccheckdll.dll")
constant libwrap = open_dll("ccheckwrap.dll")
--constant stdcall = "+"
constant stdcall = ""
elsifdef UNIX then
constant libdll = open_dll("ccheckdll.so")
constant libwrap = open_dll("ccheckwrap.so")
constant stdcall = ""
elsedef
puts(2, "OS not supported yet\n")
abort(1)
end ifdef
It should read:
ifdef WINDOWS then
constant libdll = open_dll("ccheckdll.dll")
constant libwrap = open_dll("ccheckwrap.dll")
constant cdecl = "+"
constant stdcall = ""
constant default_convention = stdcall
elsifdef UNIX then
constant libdll = open_dll("ccheckdll.so")
constant libwrap = open_dll("ccheckwrap.so")
constant cdecl = ""
constant default_convention = cdecl
elsedef
puts(2, "OS not supported yet\n")
abort(1)
end ifdef
constant convention = default_convention
And then prefix 'convention' with everything instead of 'stdcall' or not at all.
16. Comment by mattlewis
Jun 30, 2011
The calling convention is determined by the author of the library. The author of the Win32 API decided long ago to use STDCALL. That does not prevent (nor has it!) anyone on windows to release libraries with different conventions. How he does so is compiler specific.
There are plenty of libraries for Windows that use cdecl. Watcom is a little weird. I think that it does some extra work to restore the stack after a call, so you can actually mess up the calling convention at times and have things work. So, likely, it was a bug that was there the whole time, but was being hidden by a quirk in Watcom.
17. Comment by ne1uno
Jul 01, 2011
thanks Shawn for the corrected code, I admit to being confused as to which convention requires '+' there are examples both ways in various forum posts and in previous docs. compounded by the fact that watcom works either way. before this ticket and gcc 4.5 so did minGW.
I believe eumario reverted the change which is why everything still worked in 4.0 and 4.1, for me anyway. not sure there are tests to expose the exact bug I was seeing.