puma: Native extension build failure on MRI 2.4.0 linked against OpenSSL 1.1.0*

MRI 2.4.0 changed OpenSSL compatibility, adding 1.1.*. It looks like the Puma native ext currently uses an OpenSSL ABI < 1.1. Probably worth supporting 0.98-1.1 as Ruby 2.4 does.

There’s also a new OpenSSL cpp flag (ie -DOPENSSL_API_COMPAT=0x10000000L) for apps to ensure they are compiling against a compatible OpenSSL installation.

Steps to reproduce (macOS example)

brew install openssl openssl@1.1 ruby-install chruby
mkdir -p /opt/rubies
ruby-install ruby-2.4.0 --no-install-deps -i /opt/rubies/ruby-2.4.0-ossl1.1 -- --without-X11 --without-tk --disable-install-doc --with-openssl-dir="$(brew --prefix openssl@1.1)" --enable-shared
chruby-exec ruby-2.4.0-ossl1.1 -- gem install puma -v 3.6.2 -N
# watch it crash

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 14
  • Comments: 16 (4 by maintainers)

Most upvoted comments

Meet same problem with OpenSSL 1.1.0e and Puma 3.8.0, using Ruby 2.4.0.

$ gem install puma -v 3.8.0
Building native extensions.  This could take a while...
ERROR:  Error installing puma:
        ERROR: Failed to build gem native extension.

    current directory: /var/www/site/.rvm/gems/ruby-2.4.0/gems/puma-3.8.0/ext/puma_http11
/var/www/site/.rvm/rubies/ruby-2.4.0/bin/ruby -r ./siteconf20170313-13337-26j4we.rb extconf.rb
checking for BIO_read() in -lcrypto... yes
checking for SSL_CTX_new() in -lssl... yes
checking for openssl/bio.h... yes
creating Makefile

current directory: /var/www/site/.rvm/gems/ruby-2.4.0/gems/puma-3.8.0/ext/puma_http11
make "DESTDIR=" clean

current directory: /var/www/site/.rvm/gems/ruby-2.4.0/gems/puma-3.8.0/ext/puma_http11
make "DESTDIR="
compiling http11_parser.c
In file included from ext/puma_http11/http11_parser.rl:8:0:
ext/puma_http11/http11_parser.rl: In function ‘puma_parser_execute’:
ext/puma_http11/http11_parser.rl:111:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
ext/puma_http11/http11_parser.rl: At top level:
cc1: warning: unrecognized command line option "-Wno-self-assign" [enabled by default]
cc1: warning: unrecognized command line option "-Wno-constant-logical-operand" [enabled by default]
cc1: warning: unrecognized command line option "-Wno-parentheses-equality" [enabled by default]
cc1: warning: unrecognized command line option "-Wno-tautological-compare" [enabled by default]
compiling io_buffer.c
compiling mini_ssl.c
In file included from mini_ssl.c:14:0:
/usr/include/openssl/bio.h: In function ‘DEPRECATEDIN_1_1_0’:
/usr/include/openssl/bio.h:671:1: error: expected declaration specifiers before ‘DEPRECATEDIN_1_1_0’
 DEPRECATEDIN_1_1_0(int BIO_get_port(const char *str, unsigned short *port_ptr))
 ^
/usr/include/openssl/bio.h:678:2: error: expected declaration specifiers before ‘;’ token
 };
  ^
In file included from /usr/include/openssl/asn1.h:24:0,
                 from /usr/include/openssl/objects.h:916,
                 from /usr/include/openssl/evp.h:27,
                 from /usr/include/openssl/x509.h:23,
...

I tried to use the following command, and it works! Thanks @cybercode

DISABLE_SSL=true gem install puma -v 3.8.0

I have the same problem as OP.

i can build but cant run: puma_http11.so: undefined symbol: DH_set0_pqg

my stuff:

  • puma (3.8.2)
  • libressl-2.4.5
  • ruby-2.4.1

installing 3.7.1 fixed the issue for me

gem ‘puma’, ‘~> 3.7.1’

With LibreSSL, on alpine:3.5, puma 3.7+ compiles but fails when trying to call DH_set0_pqg

Note that it will compile and run fine if DISABLE_SSL is set at build time (for obvious reasons)

The affected code (from mini_ssl.c)

#if OPENSSL_VERSION_NUMBER < 0x10100005L
  dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);

  if ((dh->p == NULL) || (dh->g == NULL)) {
    DH_free(dh);
    return NULL;
  }
#else
  BIGNUM *p, *g;
  p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
  g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);

  if (p == NULL || g == NULL || !DH_set0_pqg(dh, p, NULL, g)) {
    DH_free(dh);
    BN_free(p);
    BN_free(g);
    return NULL;
  }
#endif

A possible solution:

6	#define LIBRESSL_VERSION_NUMBER	0x2050200fL
7	#define LIBRESSL_VERSION_TEXT	"LibreSSL 2.5.2"
8	
9	/* These will never change */
10	#define OPENSSL_VERSION_NUMBER	0x20000000L
11	#define OPENSSL_VERSION_TEXT	LIBRESSL_VERSION_TEXT

3.8.2: tastes great and less filling! 🍻

$ chruby-exec ruby-2.4.0-ossl1.1 -- gem install puma -N
Building native extensions.  This could take a while...
Successfully installed puma-3.8.2
1 gem installed

Same here with alpine:3.5, MRI 2.3.3, OpenSSL 1.0.2k:

LoadError: Error relocating /app/vendor/ruby/2.3.0/gems/puma-3.8.1/lib/puma/puma_http11.so: DH_set0_pqg: symbol not found - /app/vendor/ruby/2.3.0/gems/puma-3.8.1/lib/puma/puma_http11.so