mysql2
mysql2 copied to clipboard
Segmentation fault in `connect` when password provided on macOS 10.15 running MySQL 5.6
I get the following segmentation fault in Mysql2::Client.new when running on macOS 10.15 (19A602), against MySQL 5.6.43 installed via Homebrew, if and only if a password is provided for the user:
tthomas@Todds-Mac mysql2_test % ruby mysql2-test.rb
/Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90: [BUG] Segmentation fault at 0x00007ffeee651000
ruby 2.5.5p157 (2019-03-15 revision 67260) [x86_64-darwin19]
-- Crash Report log information --------------------------------------------
See Crash Report log file under the one of following:
* ~/Library/Logs/DiagnosticReports
* /Library/Logs/DiagnosticReports
for more details.
Don't forget to include the above Crash Report log file in bug reports.
-- Control frame information -----------------------------------------------
c:0005 p:---- s:0039 e:000038 CFUNC :connect
c:0004 p:0612 s:0027 e:000026 METHOD /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90 [FINISH]
c:0003 p:---- s:0013 e:000012 CFUNC :new
c:0002 p:0025 s:0008 E:0023d0 EVAL mysql2-test.rb:3 [FINISH]
c:0001 p:0000 s:0003 E:001ee0 (none) [FINISH]
-- Ruby level backtrace information ----------------------------------------
mysql2-test.rb:3:in `<main>'
mysql2-test.rb:3:in `new'
/Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `initialize'
/Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `connect'
-- Machine register context ------------------------------------------------
rax: 0x00007ffeee64f25d rbx: 0x0000000101be5568 rcx: 0x0000000101be3cc8
rdx: 0x0000000101be5568 rdi: 0x00007ffeee650afd rsi: 0x00007ffeee651000
rbp: 0x00007ffeee64f1f0 rsp: 0x00007ffeee64f1f0 r8: 0x00007ff3c0e98600
r9: 0xffffffff807ff7ff r10: 0x0000000101be5568 r11: 0xfffffffffffffafd
r12: 0x0000ffff55387f57 r13: 0x00007ff3c1067200 r14: 0x00007ffeee64f760
r15: 0x00007ffff02347c5 rip: 0x00007fff65148d29 rfl: 0x0000000000010202
-- C level backtrace information -------------------------------------------
0 0x00000001017b0e18 rb_vm_bugreport + 136
1 0x000000010162a9b6 rb_bug_context + 470
2 0x000000010171ef51 sigsegv + 81
3 libsystem_platform.dylib 0x00007fff6514bb1d _sigtramp + 29
4 libsystem_platform.dylib 0x00007fff65148d29 _platform_memmove$VARIANT$Haswell + 41
-- Other runtime information -----------------------------------------------
* Loaded script: mysql2-test.rb
* Loaded features:
0 enumerator.so
1 thread.rb
2 rational.so
3 complex.so
4 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/enc/encdb.bundle
5 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/enc/trans/transdb.bundle
6 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/rbconfig.rb
7 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/compatibility.rb
8 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/defaults.rb
9 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/deprecate.rb
10 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/errors.rb
11 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/version.rb
12 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/requirement.rb
13 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/platform.rb
14 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/basic_specification.rb
15 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/stub_specification.rb
16 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/util/list.rb
17 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/stringio.bundle
18 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/rfc2396_parser.rb
19 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/rfc3986_parser.rb
20 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/common.rb
21 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/generic.rb
22 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/ftp.rb
23 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/http.rb
24 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/https.rb
25 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/ldap.rb
26 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/ldaps.rb
27 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri/mailto.rb
28 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/uri.rb
29 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/specification.rb
30 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/exceptions.rb
31 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/dependency.rb
32 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/core_ext/kernel_gem.rb
33 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/monitor.rb
34 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/core_ext/kernel_require.rb
35 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems.rb
36 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/path_support.rb
37 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/version.rb
38 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/core_ext/name_error.rb
39 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/levenshtein.rb
40 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/jaro_winkler.rb
41 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checker.rb
42 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/delegate.rb
43 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
44 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
45 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/name_error_checkers.rb
46 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/method_name_checker.rb
47 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/key_error_checker.rb
48 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/spell_checkers/null_checker.rb
49 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean/formatters/plain_formatter.rb
50 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/did_you_mean-1.2.0/lib/did_you_mean.rb
51 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/bundler_version_finder.rb
52 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/rubygems/util.rb
53 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/date_core.bundle
54 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/date.rb
55 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin19/bigdecimal.bundle
56 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/version.rb
57 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/error.rb
58 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/mysql2.bundle
59 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/result.rb
60 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb
61 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/field.rb
62 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/statement.rb
63 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/2.5.0/timeout.rb
64 /Users/tthomas/.rbenv/versions/2.5.5/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2.rb
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html
[IMPORTANT]
Don't forget to include the Crash Report log file under
DiagnosticReports directory in bug reports.
zsh: abort ruby mysql2-test.rb
I initially saw this with mysql2 v. 0.4.10, but it persisted after updating to 0.5.2.
The test program that produced that output was
require 'mysql2'
client = Mysql2::Client.new(:host => "localhost", :username => "pwd", :password => "pwd")
results = client.query("SELECT * FROM reviews")
puts results
(I realize the query in that program would have failed because no database was selected, but the segfault occurs on line 3 before the query. I've used various forms of that test program, including ones where a :database key-value pair was passed to new, but the segfault always and only occurs when the :password key-value pair is passed.)
MySQL was installed via
brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/f171f1c74/Formula/[email protected]
That version of the formula was used in order to get MySQL 5.6.43, instead of 5.6.46, which is what the latest version of the formula installs. Currently mysql2 can't be built against 5.6.46 due to https://github.com/Homebrew/homebrew-core/issues/45397.
A more interesting C stack trace can be obtained from lldb:
tthomas@Todds-Mac mysql2_test % bundle exec lldb -- ruby mysql2-test.rb
(lldb) target create "ruby"
Current executable set to 'ruby' (x86_64).
(lldb) settings set -- target.run-args "mysql2-test.rb"
(lldb) run
Process 5673 launched: '/Users/tthomas/.rbenv/versions/2.5.5/bin/ruby' (x86_64)
Process 5673 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7ffeefc00000)
frame #0: 0x00007fff65148d29 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 41
libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell:
-> 0x7fff65148d29 <+41>: rep movsb (%rsi), %es:(%rdi)
0x7fff65148d2b <+43>: popq %rbp
0x7fff65148d2c <+44>: retq
0x7fff65148d2d <+45>: cmpq %rdi, %rsi
Target 0: (ruby) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7ffeefc00000)
* frame #0: 0x00007fff65148d29 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 41
frame #1: 0x0000000102009372 libmysqlclient.18.dylib`write_length_encoded_string4 + 54
frame #2: 0x000000010200befb libmysqlclient.18.dylib`send_client_reply_packet + 1115
I think this is a problem with MySQL, not the mysql2 gem, but I'm not certain. I wrote a C program that uses the MySQL client lib to try to reproduce the problem outside of the context of the mysql2 gem and the Ruby interpreter.
//
// main.c
// mysql_test
//
// Build like so: `clang $(mysql_config --cflags) $(mysql_config --libs) -L/usr/local/opt/openssl/lib main.c`
//
// If `mysql_options4` is called, *and* a password is passed to `mysql_real_connect`, a segfault will occur
// during the call to `mysql_real_connect`.
//
// For example, if the database has a user named "nopassword", which requires no password, and a user named
// "password", which requires the password "password", then the program yields the following results:
//
// ./a.out -unopassword # success
// ./a.out -unopassword --options4 # success
// ./a.out -upassword -ppassword # success
// ./a.out -upassword -ppassword --options4 # segfault
//
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[]) {
const char* host = "localhost";
const char* user = "";
const char* password = NULL;
const char * const k_options4_arg_name = "--options4";
int call_mysql_options4 = 0;
// I know this is not the most efficient, idiomatic C command-line processing. Sorry, it's been a long time since I wrote C for a living.
// This is only here so testing with and without a password can be done without recompiling.
for (int i = 1; i < argc; i++) {
const char* arg = argv[i];
if (strlen(arg) > 2 && strncmp("-h", arg, 2) == 0) {
host = arg + 2;
} else if (strlen(arg) > 2 && strncmp("-u", arg, 2) == 0) {
user = arg + 2;
} else if (strlen(arg) > 2 && strncmp("-p", arg, 2) == 0) {
password = arg + 2;
} else if (strncmp(k_options4_arg_name, arg, strlen(k_options4_arg_name)) == 0) {
call_mysql_options4 = 1;
} else {
fprintf(stderr, "Usage: %s -u<username> [-p<password> [default: NULL]] [-h<hostname> [default: localhost]] [%s [default: false]]\n", argv[0], k_options4_arg_name);
exit(1);
}
}
if (strlen(user) == 0) {
fprintf(stderr, "must specify -u<username>\n");
exit(1);
}
MYSQL mysql;
mysql_init(&mysql);
int err;
if (call_mysql_options4) {
// Segfault in `mysql_real_connect` only occurs if `mysql_options4` is called and a password is passed to `mysql_real_connect`.
err = mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "/Users/tthomas/src/mysql_test/main.c");
printf("mysql_options4 returned %d\n", err);
} else {
// If `mysql_options` is called instead of `mysql_options4`, then the segfault does not occur, regardless of whether a password is
// passed to `mysql_real_connect`.
err = mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "/Users/tthomas/src/mysql_test/main.c");
printf("mysql_options returned %d\n", err);
}
// Setting a connect timeout doesn't seem to have any effect on whether the segfault occurs.
//int timeout = 20;
//err = mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
//printf("mysql_options returned %d\n", err);
// Set the same connect flags as the mysql2 gem does by default.
unsigned long flags = CLIENT_PROTOCOL_41 | CLIENT_TRANSACTIONS | CLIENT_SECURE_CONNECTION | CLIENT_LONG_FLAG | CLIENT_CONNECT_ATTRS | CLIENT_LONG_PASSWORD | CLIENT_REMEMBER_OPTIONS;
printf("Using connect flags %lu\n", flags);
// Segfault occurs when the next line is executed if `mysql_options4` was called previously, and password is passed.
if (!mysql_real_connect(&mysql, host, user, password, NULL, 0, NULL, flags)) {
fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
exit(1);
}
// The rest of this program just exercises the connection, if we were able to obtain one.
unsigned long version = mysql_get_server_version(&mysql);
printf("MySQL version is %lu\n", version);
mysql_close(&mysql);
return 0;
}
When the segfault happens with this C program, the backtrace is the same as with the mysql2 program:
tthomas@Todds-Mac mysql_test % lldb -- a.out -upwd -ppwd --options4
(lldb) target create "a.out"
Current executable set to 'a.out' (x86_64).
(lldb) settings set -- target.run-args "-upwd" "-ppwd" "--options4"
(lldb) run
Process 10967 launched: '/Users/tthomas/src/mysql_test/a.out' (x86_64)
mysql_options4 returned 0
Using connect flags 2148573701
Process 10967 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7ffeefc00000)
frame #0: 0x00007fff65148d29 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 41
libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell:
-> 0x7fff65148d29 <+41>: rep movsb (%rsi), %es:(%rdi)
0x7fff65148d2b <+43>: popq %rbp
0x7fff65148d2c <+44>: retq
0x7fff65148d2d <+45>: cmpq %rdi, %rsi
Target 0: (a.out) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x7ffeefc00000)
* frame #0: 0x00007fff65148d29 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 41
frame #1: 0x000000010010e372 libmysqlclient.18.dylib`write_length_encoded_string4 + 54
frame #2: 0x0000000100110efb libmysqlclient.18.dylib`send_client_reply_packet + 1115
Given that the call to mysql_options4 is essential for the segfault in the above program, I thought I could work around the problem in mysql2 by omitting its call to mysql_options4 with this change:
diff --git a/ext/mysql2/client.c b/ext/mysql2/client.c
index 2926571..2cd4c45 100644
--- a/ext/mysql2/client.c
+++ b/ext/mysql2/client.c
@@ -429,7 +429,7 @@ static VALUE rb_mysql_connect(VALUE self, VALUE user, VALUE pass, VALUE host, VA
args.mysql = wrapper->client;
args.client_flag = NUM2ULONG(flags);
-#ifdef CLIENT_CONNECT_ATTRS
+#ifdef CLIENT_CONNECT_ATTRS_NOPE
mysql_options(wrapper->client, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
rb_hash_foreach(conn_attrs, opt_connect_attr_add_i, (VALUE)wrapper);
#endif
But that didn't work--I still got the segfault when using a gem built from that code.
I verified all of the above using a fresh install of macOS 10.15 in a VMware Fusion virtual machine, and in a virtual machine that started as a fresh install of macOS 10.14 and then was upgraded to 10.15. In the latter case, I could not reproduce the problem on 10.14, nor could I reproduce it immediately after upgrading to 10.15. I had to do brew reinstall https://raw.githubusercontent.com/Homebrew/homebrew-core/f171f1c74/Formula/[email protected] after the upgrade to 10.15 before I could reproduce the problem. That mirrors how I initially encountered this. The mysql2 gem had been working fine after I upgraded my dev machine’s 10.14 installation to 10.15. It was only after a brew upgrade upgraded MySQL from 5.6.43 to 5.6.46 that I saw this problem. I then had to revert to 5.6.43 due to the linking issue mentioned above, but this segfault issue persisted.
Thank you for the thorough bug report and your initial efforts at debugging this! What a weird crash. I'm not sure off the cuff what action to take to avoid triggering this, or whether it's really a MySQL bug that should be filed upstream, but will look into it as well.
Thank you. I debated whether to log this issue here or against Homebrew's [email protected] formula, but I decided that since I first encountered it in the context of mysql2, and my C program is just a naive attempt to mimic what mysql2 does with the MySQL client lib, I should log it here first to see what mysql2 experts think. But it does seem like it's ultimately something wrong with MySQL on Catalina, or Homebrew's formula.
I forgot to mention toolchain versions. On the 10.14 virtual machine, I didn't take the time to install Xcode. Homebrew installed the command-line tools corresponding to Xcode 10:
Todds-Mac:mysql_test tthomas$ xcode-select -p
/Library/Developer/CommandLineTools
Todds-Mac:mysql_test tthomas$ clang --version
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
On the 10.15 virtual machine, Homebrew installed the Xcode 11 command-line tools:
tthomas@Todds-Mac mysql_test % xcode-select -p
/Library/Developer/CommandLineTools
tthomas@Todds-Mac mysql_test % clang --version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
On the 10.14->10.15 VM, I installed Xcode 11.1 before the upgrade to 10.15, because that's what I had done on my dev machine. The resulting clang seems to be the same as what Homebrew installed on the 10.15 VM:
Todds-Mac:mysql_test tthomas$ xcode-select -p
/Applications/Xcode.app/Contents/Developer
Todds-Mac:mysql_test tthomas$ clang --version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
+1
New learnings:
- updating to macOS 10.15.1 doesn't fix the problem for MySQL 5.6;
- however, the problem doesn't occur when using MySQL 5.7.28 via
brew install [email protected]for either 10.15 or 10.15.1.
In the latter case, I did have to run mysql_upgrade and then restart the server after installing and running 5.7. I also recompiled my test program and reinstalled the mysql2 gem so they were linked against /usr/local/opt/[email protected]/lib/libmysqlclient.20.dylib.
So, there are currently two workarounds for this:
- use MySQL 5.7 instead of 5.6 if you can;
- if you must use 5.6, use an account without a password 😳
The problem that prevented building mysql2 against MySQL 5.6.46 installed via Homebrew's [email protected] formula has been fixed. However, this seg fault issue still occurs with 5.6.46 installed via the fixed formula.
@toddthomas - Thanks a lot, installing MySQL 5.7 helped me to resolve the issue. Steps that I followed
- brew install [email protected]
- brew unlink [email protected]
- brew link [email protected] --force
- mysql --version mysql Ver 14.14 Distrib 5.7.28, for osx10.15 (x86_64) using EditLine wrapper
- gem list mysql2 *** LOCAL GEMS *** mysql2 (0.3.21)
- gem install mysql2 -v '0.3.21' -- --with-cflags="-I/usr/local/opt/openssl/include" --with-ldflags="-L/usr/local/opt/openssl/lib"
- bundle install
@toddthomas great bug report!
Is there any update on this, or another place to track it?
@kastner I have no new info. I've been using the "don't use a password" workaround since I need MySQL 5.6.
I have a notion that not a lot of people are running into this, because Homebrew installs MySQL without a root password by default, and devs are okay with that on their dev machines. Their prod instances are presumably deployed on something other than macOS that doesn't have this problem.
I haven't logged this issue anywhere else. I probably should log it directly against MySQL. But I'm not likely to get to that soon.
@toddthomas Thanks for the reply!
For local development, I am also going with no password (luckily https://github.com/bkeepers/dotenv supports overriding overrides - e.g. .env.local to supercede the checked-in .env.development)
The reason I still care about it is I'm unable to connect to a remote server with a password, using the mysql client (like a hosted staging environment's database). Not the biggest deal in the world, but it's an annoyance.
Thanks for the writeup! I just wasted three hours on this until I discovered the mysql no-password workaround and this issue.
I ran into this issue on my mac and came to some conclusions that may be able to help. I was debugging this application https://github.com/ScottRobbins/RailsMultipleDatabaseIssue) from this issue on Rails https://github.com/rails/rails/issues/36894.
I was able to reliably reproduce it with bin/rake db:create on Ruby 2.6.5 in this sample app. I was able to "fix" this locally by reinstalling Ruby 2.6.5.
Here's my segfault: https://gist.github.com/eileencodes/03e20d831a2b4794aaabef011fda2c8c
My reproduction was on macOS Catalina (brand new, not an upgrade), both mysql2 0.5.2 and 0.5.3 with mysql 5.7.28. I was not able to reproduce in the same conditions with Ruby 2.6.4 or 2.7.0.
My mysql user does no have a password either. I also was not able to reproduce on 2.6.5 with High Sierra.
I got a core dump and @jhawthorn helped me investigate. We found that it appeared there was a bad client. I also noticed a similar issue #1076 that mentioned the client being wrong. Due to the core dump and the other issue I looked at the libmysqlclient versions that were linked and here's what I found:
2.6.5 is clearly linked to libmysqlclient.21
$ otool -L ~/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle
/Users/eileencodes/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle:
/Users/eileencodes/.rbenv/versions/2.6.5/lib/libruby.2.6.dylib (compatibility version 2.6.0, current version 2.6.5)
/usr/local/opt/mysql/lib/libmysqlclient.21.dylib (compatibility version 21.0.0, current version 21.0.0)
/usr/local/opt/[email protected]/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/local/opt/[email protected]/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
While 2.6.4 and 2.7.0 are linked to libmysqlclient.20
$ otool -L ~/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle
/Users/eileencodes/.rbenv/versions/2.6.4/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle:
/Users/eileencodes/.rbenv/versions/2.6.4/lib/libruby.2.6.dylib (compatibility version 2.6.0, current version 2.6.4)
/usr/local/opt/[email protected]/lib/libmysqlclient.20.dylib (compatibility version 20.0.0, current version 20.0.0)
/usr/local/opt/[email protected]/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/local/opt/[email protected]/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
$ otool -L ~/.rbenv/versions/2.7.0-dev/lib/ruby/gems/2.7.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle
/Users/eileencodes/.rbenv/versions/2.7.0-dev/lib/ruby/gems/2.7.0/gems/mysql2-0.5.3/ext/mysql2/mysql2.bundle:
/usr/local/opt/[email protected]/lib/libmysqlclient.20.dylib (compatibility version 20.0.0, current version 20.0.0)
/usr/local/opt/[email protected]/lib/libssl.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/local/opt/[email protected]/lib/libcrypto.1.1.dylib (compatibility version 1.1.0, current version 1.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.0.0)
When I checked my [email protected] libary for the libmysqlclient version it was linked to 20. I have no idea how 21 got in there, or why it was linked to the wrong version. I did have a hard time getting everything running (libxml-ruby and mysql2 gems were failing to install due to libxml2 and openssl issues) so it's possible I ran a command that was incorrect at some point. My Rails source copy however was able to create databases just fine on 2.6.5. It's definitely a strange issue. I hope this helps!
Same issue on Ruby 2.1.5, [email protected] homebrew, OSX 10.15.2 Catalina, and DataMapper as the ORM, which rolls its own adapter. The segfault occurs when DM attempts to connect using libmysqlclient.18.dylib, reinforcing the idea that the issue is with MySQL rather than mysql2.
I had the fortune of having a project configured for both Active Record and Datamapper, and was able to observe identical crash logs when running with either configuration. Configuring a new user without a password and connecting with that user is my workaround until this is fixed.
I just ran brew upgrade [email protected] a moment ago and this seems to have fixed the issue for me.
I just ran
brew upgrade [email protected]a moment ago and this seems to have fixed the issue for me.
solved the issue for me on macos catalina 10.15.1, upgraded [email protected] 5.6.46_2 -> 5.6.47, and reinstalled the mysql2 gem. Thanks a lot
I just ran
brew upgrade [email protected]a moment ago and this seems to have fixed the issue for me.
Works for mac os 10.15.2 with mysql 5.6.47... has anybody tried with mac os latest catalina update 10.15.4?
For the reference, this also happens on Ubuntu 22.04 LTS and non-system builds of ruby-2.7.0.
Ubuntu 22.04 ships with OpenSSL v3 but ruby-2.7.0 requires OpenSSL <= 1.1 to work. I was able to build ruby-2.7.0 through rvm with:
rvm pkg install openssl
rvm install ruby-2.7.0 -C --with-openssl-dir=$HOME/.rvm/usr
In such envrionment, mysql2 gem compiled without problems, but it was seg faulting on the connect method.
My guess is that it was using the system libmysqlclient-dev library which is likely using the system's libcrypto.so.3 while ruby was compiled by rvm with libcrypto.so.1.0.0.
Using a blank password for the database connection helped.
I also face the same problem in Ubuntu 22.04 and for Rails 5.0. Resolved just uninstall MySQL and install MariaDB
- Install mariaDB instad of MySQL.
- sudo apt install libmariadb-dev-compat libmariadb-dev Also, follow the link - https://medium.com/francium-tech/setting-up-ruby-2-7-6-on-ubuntu-22-04-fdb9560715f7