mysql
mysql copied to clipboard
Segmentation fault when using mysql on Windows
I'm trying to use mysql-0.1.1.8 on a Windows system. I managed to circumvent https://github.com/bos/mysql/issues/3 by passing the flags manually via --extra-include/lib-dirs
to cabal. However, there are more problems because pthread is not supported on Windows systems. Using pthreads-win32 (http://www.sourceware.org/pthreads-win32/) still leads to errors because several definitions from signal.h
are not found in my MinGW installation.
As all the pthread functions only seem to be used to avoid RTS interruptions, I removed mysql_signals.h
and mysql_signals.c
from the project and changed the foreign import calls in Database.MySQL.Base.C
back to their original names, e.g.
foreign import ccall unsafe "mysql_signals.h _hs_mysql_real_connect"
becomes
foreign import ccall unsafe mysql_real_connect
etc.
After doing these changes the package builds fine, the following test program builds fine and there aren't any linker errors anymore.
module Main where
import Control.Exception
import Database.MySQL.Base
main :: IO ()
main = do
putStrLn $ "Client info: " ++ clientInfo
handle (\e -> putStrLn $ "ERROR: " ++ show (e :: MySQLError)) $ do
conn <- connect $ ConnectInfo {
connectHost = "localhost",
connectUser = "root",
connectPassword = "pass",
connectDatabase = "",
connectPort = 0,
connectOptions = [],
connectPath = "",
connectSSL = Nothing
}
info <- serverInfo conn
putStrLn $ "Server info: " ++ info
close conn
The only problem is the program produces a segmentation fault when run:
Client info: 5.0.51a
Segmentation fault/access violation in generated code
Note that the call to clientInfo
works fine, but the attempt to connect to the database segfaults. I thought it might be an incompatible MySQL version of something like that, so I wrote a small C program doing basically the same function calls, and that works fine:
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <mysql.h>
int main(int argc, char **argv)
{
MYSQL *conn = mysql_init(NULL);
if (conn == NULL) {
printf("%s\n", mysql_error(conn));
exit(1);
}
printf("Client info: %s\n", mysql_get_client_info());
if (mysql_real_connect(conn, "localhost", "root", "pass", NULL, 0, NULL, 0) == NULL) {
printf("%s\n", mysql_error(conn));
mysql_close(conn);
exit(1);
}
printf("Server info: %s\n", mysql_get_server_info(conn));
mysql_close(conn);
exit(0);
}
outputs
Client info: 5.0.51a
Server info: 5.1.32-community
Performing SQL requests and fetching the result also works fine in C. So the problem clearly is related to the Haskell package, but I have no idea where to start debugging this. May it be the changes I did to the package causing this problem? I would try using the functions from Database.MySQL.Base.C
directly but I'm not familiar with the FFI, so I don't know how to use them safely.
Any ideas on that?
Finally, I've managed to get mysql to work. Maybe someone had similar trouble, so here's an explanation of what I did:
-
Remove all references to
mysql_signals.h
andmysql_signals.c
from the cabal file. These files won't be used for compilation. -
In the cabal file, add
extra-libraries: libmysql
to the library section. -
In modules
Database\MySQL\Base\C.hsc
andDatabase\MySQL\Base\Types.hsc
add#include <winsock.h>
before the include of
mysql.h
. -
Also in module
Database\MySQL\Base\C.hsc
, replace all foreign imports frommysql_signals.h
by their original function name, i.e. remove the quoted part from the import declaration. While doing that, also replace the call method fromccall
tostdcall
. Note that this needs to be done for all imports while renaming the import has to be done only for the functions redefined viamysql_signals.h
. As an example, the lineforeign import ccall unsafe "mysql_signals.h _hs_mysql_real_connect" mysql_real_connect
becomes
foreign import stdcall unsafe mysql_real_connect
-
Find a way to circumvent https://github.com/bos/mysql/issues/3. What I did was replacing
Setup.lhs
with a simple setup file:> import Distribution.Simple > main = defaultMain
This requires you to pass the include and lib options yield by
mysql_config
to cabal manually. -
Configure cabal with the paths to the mysql header and lib files.
cabal configure --extra-include-dirs=<path-to-mysql>/include --extra-lib-dirs=<path-to-mysql>/lib/opt --ld-options="-L<path-to-mysql>/lib/opt -llibmysql"
-
Build the package as usual (
cabal build; cabal install
). You shouldn't get any compilation or linker error here anymore.
After that, the example from my previous comment should also compile and link fine, and running it shouldn't yield a segmenation fault anymore. Running the program from GHCi should also work.
I'm aware that this is a terrible hack and some MySQL features may not work correctly (or at all), and there still is the risk of GHC's RTS interfering with the SQL connection requests. But for me the basic functions for sending requests and fetching data work fine, so I don't really care at the moment.
Any comments or suggestions of a more sane way to build the package on Windows are welcome, of course.
Thanks for documenting this. Are you building for 64-bit?
No, I'm using an older 32-bit Windows XP system.