Bug #62574 | libmysqlclient statically compiled, mysql_close() hangs | ||
---|---|---|---|
Submitted: | 29 Sep 2011 17:19 | Modified: | 5 Oct 2011 14:08 |
Reporter: | Dario Fiumicello | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | MySQL Server: C API (client library) | Severity: | S2 (Serious) |
Version: | 5.1.49 | OS: | Linux (Debian) |
Assigned to: | CPU Architecture: | Any | |
Tags: | static statically libmysqlclient c mysql_close hang |
[29 Sep 2011 17:19]
Dario Fiumicello
[30 Sep 2011 12:49]
Valeriy Kravchuk
Please, check if the same problem still happens with a newer version, 5.1.59 (use official community binaries if possible). If it does, please, send code of smallest application that demonstrates the problem.
[30 Sep 2011 21:46]
Dario Fiumicello
I tried the program below with both 5.1.49 and 5.1.59. It worked correctly with those two versions. compiled with: gcc -lm -g mysql_test.c libmysqlclient.a -o mysql_test Then I tried to debug my program using 5.1.59 and I got the same error. GDB reported this: Program received signal SIGSEGV, Segmentation fault. 0x081e8830 in shutdown () (gdb) ^CQuit (gdb) bt #0 0x081e8830 in shutdown () #1 0x0807f328 in vio_close (vio=0x81ea2d0) at viosocket.c:275 #2 0x0807ebe1 in vio_delete (vio=0x81ea2d0) at vio.c:238 #3 0x0807a423 in end_server (mysql=0xbffff87c) at client.c:951 #4 0x0807a5ca in mysql_close (mysql=0xbffff87c) at client.c:2771 #5 0x0805404c in mysqlStart (config=0xbffff634) at mysql_output.c:82 #6 0x0804efa3 in collectorStart (argc=1, argv=0xbffffd24, config=0xbffff634, client=0x81e7c90) at collector.c:413 #7 0x0804e13c in main (argc=1, argv=0xbffffd24) at collector.c:147 (gdb) As you can see the segfault starts exactly when program enters in shutdown(). Also you can see that since libmysqlclient is compiled statically the adresses are 0x080xxxxx as far as they arrive to shutdown; then they became 0x081xxxxx and... SIGSEGV. Line at viosocket.c:275 simply does: if (shutdown(vio->sd, SHUT_RDWR)) I set a breakpoint at it and when it is called vio->sd exists (it is set to 5) and is reported by lsof to be a valid descriptor: collector 5049 root 5u sock 0,6 0t0 18720 can't identify protocol If I execute the program with libmysqlclient linked dinamically and set a breakpoint at the same place everything goes fine: Breakpoint 1, vio_close (vio=0x80562d0) at viosocket.c:275 275 viosocket.c: No such file or directory. in viosocket.c (gdb) bt #0 vio_close (vio=0x80562d0) at viosocket.c:275 #1 0xb7e5d091 in vio_delete (vio=0x80562d0) at vio.c:238 #2 0xb7e588d3 in end_server (mysql=0xbffff87c) at client.c:951 #3 0xb7e58a7a in mysql_close (mysql=0xbffff87c) at client.c:2771 #4 0x0804f3dc in mysqlStart (config=0xbffff634) at mysql_output.c:82 #5 0x0804a333 in collectorStart (argc=1, argv=0xbffffd24, config=0xbffff634, client=0x8054910) at collector.c:413 #6 0x080494cc in main (argc=1, argv=0xbffffd24) at collector.c:147 (gdb) s shutdown () at ../sysdeps/unix/sysv/linux/i386/socket.S:51 51 ../sysdeps/unix/sysv/linux/i386/socket.S: No such file or directory. in ../sysdeps/unix/sysv/linux/i386/socket.S Current language: auto The current source language is "auto; currently asm". (gdb) As you can see it correctly steps into shutdown() I suspect there is something wrong when jumping into shutdown() routine, maybe the address space is not correct when using statically linked libraries. It could be a libc bug or something else, I don't know. Anyway I didn't explain why it didn't happens whit the sample test program. The sample program: /* Simple C program that connects to MySQL Database server*/ #include <mysql.h> #include <stdio.h> main() { MYSQL *conn; MYSQL_RES *res; MYSQL_ROW row; char *server = "localhost"; char *user = "root"; char *password = "PASSWORD"; /* set me first */ char *database = "mysql"; conn = mysql_init(NULL); /* Connect to database */ if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); } /* send SQL query */ if (mysql_query(conn, "show tables")) { fprintf(stderr, "%s\n", mysql_error(conn)); exit(1); } res = mysql_use_result(conn); /* output table name */ printf("MySQL Tables in mysql database:\n"); while ((row = mysql_fetch_row(res)) != NULL) printf("%s \n", row[0]); /* close connection */ mysql_free_result(res); mysql_close(conn); }
[5 Oct 2011 14:08]
Dario Fiumicello
We found the issue. The segfaulting shutdown was at: 0x0807f513 <vio_close+51>: call 0x81e9850 <shutdown> Looking in our project we found that there is a struct called "shutdown". Now, guess where is the shutdown placed: gdb) print &'collector.c'::shutdown $6 = (struct {...} *) 0x81e9850 So the linker, when we use libmysqlclient statically, confuses the shutdown() call with the "shutdown" struct, thus jumping to that address produced a segfault. I don't know if it is our fault or a linker fault (which does not even prompt a warning message for this ambiguity), anyway I'm going to talk about this with the gcc guys. Sorry for the wrong report.