Ruby-build: multiple versions fail to build on OSX due to dtrace permissions

Created on 3 Mar 2017  路  7Comments  路  Source: rbenv/ruby-build

Originally documented at https://github.com/rbenv/rbenv/issues/708

Encountered this problem with rbenv install 2.3.3 and rbenv install 2.4.0

% rbenv install 2.3.3
ruby-build: use openssl from homebrew
Downloading ruby-2.3.3.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.3.tar.bz2
Installing ruby-2.3.3...
ruby-build: use readline from homebrew

BUILD FAILED (OS X 10.10.5 using ruby-build 20170201)

some potentially relevant lines from the log file generated:

[clipped]
checking for dtrace... dtrace
[clipped]
checking whether dtrace USDT is available... yes
checking whether dtrace USDT is available... (cached) yes
checking whether dtrace needs post processing... no
[clipped]
config.status: creating ruby-2.3.pc
    CC = clang
    LD = ld
    LDSHARED = clang -dynamic -bundle
    CFLAGS = -O3 -Wno-error=shorten-64-to-32  -pipe 
    XCFLAGS = -D_FORTIFY_SOURCE=2 -fstack-protector -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT -fPIE
    CPPFLAGS = -I/Users/crisher/.rbenv/versions/2.3.3/include  -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT   -I. -I.ext/include/x86_64-darwin14 -I./include -I.
    DLDFLAGS = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -fstack-protector -Wl,-u,_objc_msgSend -Wl,-pie -framework CoreFoundation  
    SOLIBS = -lgmp 
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin14.5.0
Thread model: posix
translating probes probes.d
compiling main.c
compiling dmydln.c
compiling miniinit.c
compiling dmyext.c
compiling miniprelude.c
compiling bignum.c
compiling class.c
compiling compar.c
compiling complex.c
error: unable to open output file '/dev/fd/9': 'Undefined error: 0'
1 error generated.
dtrace: failed to compile script probes.d: Preprocessor failed to process input program
make: *** [probes.h] Error 1
make: *** Waiting for unfinished jobs....

As documented in previous issue, sudo chmod -s /usr/sbin/dtrace resolves the problem. I suspect running the build as root would also resolve the problem.

Most helpful comment

Just reporting what I saw to help anyone else debugging this issue. On a coworker's machine (macOS High Sierra 10.13.3), I was getting the same error with dtrace when issuing rbenv install 2.3.6.

If I cd into the build directory and issue make myself, the output is a little easier to understand since by default ruby-build will run make with -j 8. Serializing the build makes things a little easier to follow.

I traced the failure this block in the Makefile generated after running ./configure.

.d.h:
    @$(ECHO) translating probes $<
    $(Q) $(DTRACE) -o [email protected] -h -C $(INCFLAGS) -s $<
    $(Q) sed -e 's/RUBY_/RUBY_DTRACE_/g' -e 's/PROBES_H_TMP/RUBY_PROBES_H/' -e 's/(char \*/(const char */g' -e 's/, char \*/, const char */g' [email protected] > $@
    $(Q) $(RM) [email protected]

This will at some point try to execute

dtrace -o probes.h.tmp -h -C -I. -I.ext/include/x86_64-darwin17 -I./include -I. -s probes.d

Issuing this command by itself reliably reproduces the same error

$ dtrace -o probes.h.tmp -h -C -I. -I.ext/include/x86_64-darwin17 -I./include -I. -s probes.d
error: error reading '/dev/fd/4'
1 error generated.
clang: error: unable to remove file: Operation not permitted
dtrace: failed to compile script probes.d: Preprocessor failed to process input program

Despite people having success in https://github.com/rbenv/rbenv/issues/708 and in https://github.com/Homebrew/legacy-homebrew/issues/32910, unsetting the SetUID bit on the /usr/sbin/dtrace executable had no effect for me (it was already unset).

I ended up modifying the generated ./configure script to basically always assume that dtrace is not supported on the system.

diff --git a/bin/ruby-build b/bin/ruby-build
index 57b7adc..3c5a8ac 100755
--- a/bin/ruby-build
+++ b/bin/ruby-build
@@ -558,6 +558,8 @@ build_package_standard_build() {
       use_homebrew_readline || use_freebsd_pkg ||true
   fi

+  sed -i "" 's/rb_cv_dtrace_available=yes/rb_cv_dtrace_available=no/' configure
+
   ( if [ "${CFLAGS+defined}" ] || [ "${!PACKAGE_CFLAGS+defined}" ]; then
       export CFLAGS="$CFLAGS ${!PACKAGE_CFLAGS}"
     fi

This is a ugly hack, but it makes it so that ./configure will generate a Makefile that doesn't try to build in dtrace support into Ruby.

Later, I learned that there's a --disable-dtrace option supported by Ruby's ./configure. So, without modification to ruby-build, I can issue

RUBY_CONFIGURE_OPTS="--disable-dtrace" rbenv install 2.3.6

...and ruby-build will successfully build and install Ruby

I suspect that this issue is not technically a ruby-build problem, but instead a Ruby problem. I think that the test that is used in configure.in to detect if dtrace will work correctly is not sufficient: the test will pass, so ./configure will say that dtrace is good to go, but then dtrace ends up failing during the build.

_Edit_:

On a separate macOS system where Ruby successfully builds and installs, I can see that the same dtrace command is issued without a problem. I diffed the generated Makefiles on the two systems. Besides names of our home directories differing, the only real difference is that on the working system, ruby-build ends up using the readline installed by homebrew. I don't think this difference contributes to this particular problem.

All 7 comments

Just reporting what I saw to help anyone else debugging this issue. On a coworker's machine (macOS High Sierra 10.13.3), I was getting the same error with dtrace when issuing rbenv install 2.3.6.

If I cd into the build directory and issue make myself, the output is a little easier to understand since by default ruby-build will run make with -j 8. Serializing the build makes things a little easier to follow.

I traced the failure this block in the Makefile generated after running ./configure.

.d.h:
    @$(ECHO) translating probes $<
    $(Q) $(DTRACE) -o [email protected] -h -C $(INCFLAGS) -s $<
    $(Q) sed -e 's/RUBY_/RUBY_DTRACE_/g' -e 's/PROBES_H_TMP/RUBY_PROBES_H/' -e 's/(char \*/(const char */g' -e 's/, char \*/, const char */g' [email protected] > $@
    $(Q) $(RM) [email protected]

This will at some point try to execute

dtrace -o probes.h.tmp -h -C -I. -I.ext/include/x86_64-darwin17 -I./include -I. -s probes.d

Issuing this command by itself reliably reproduces the same error

$ dtrace -o probes.h.tmp -h -C -I. -I.ext/include/x86_64-darwin17 -I./include -I. -s probes.d
error: error reading '/dev/fd/4'
1 error generated.
clang: error: unable to remove file: Operation not permitted
dtrace: failed to compile script probes.d: Preprocessor failed to process input program

Despite people having success in https://github.com/rbenv/rbenv/issues/708 and in https://github.com/Homebrew/legacy-homebrew/issues/32910, unsetting the SetUID bit on the /usr/sbin/dtrace executable had no effect for me (it was already unset).

I ended up modifying the generated ./configure script to basically always assume that dtrace is not supported on the system.

diff --git a/bin/ruby-build b/bin/ruby-build
index 57b7adc..3c5a8ac 100755
--- a/bin/ruby-build
+++ b/bin/ruby-build
@@ -558,6 +558,8 @@ build_package_standard_build() {
       use_homebrew_readline || use_freebsd_pkg ||true
   fi

+  sed -i "" 's/rb_cv_dtrace_available=yes/rb_cv_dtrace_available=no/' configure
+
   ( if [ "${CFLAGS+defined}" ] || [ "${!PACKAGE_CFLAGS+defined}" ]; then
       export CFLAGS="$CFLAGS ${!PACKAGE_CFLAGS}"
     fi

This is a ugly hack, but it makes it so that ./configure will generate a Makefile that doesn't try to build in dtrace support into Ruby.

Later, I learned that there's a --disable-dtrace option supported by Ruby's ./configure. So, without modification to ruby-build, I can issue

RUBY_CONFIGURE_OPTS="--disable-dtrace" rbenv install 2.3.6

...and ruby-build will successfully build and install Ruby

I suspect that this issue is not technically a ruby-build problem, but instead a Ruby problem. I think that the test that is used in configure.in to detect if dtrace will work correctly is not sufficient: the test will pass, so ./configure will say that dtrace is good to go, but then dtrace ends up failing during the build.

_Edit_:

On a separate macOS system where Ruby successfully builds and installs, I can see that the same dtrace command is issued without a problem. I diffed the generated Makefiles on the two systems. Besides names of our home directories differing, the only real difference is that on the working system, ruby-build ends up using the readline installed by homebrew. I don't think this difference contributes to this particular problem.

@cjlarose Thanks for the awesome debugging info!

/cc @hsbt due to possible Ruby build problem

@cjlarose @mislav I've share this information to ruby core team.

Just encountered the same issue on a mac with macOS 10.14.1 and rbenv install 2.6.1.

While looking for a solution I stumbled upon this thread as well as this one, which holds a different solution aside from disabling dtrace and also poses a different culprit (given the fact that it seems to work on some macs and not on others):

Everyone in the rvm thread seems to be running Avira anti virus software on their mac (same as in my case), which after disabling it for the install, results in a successful install with dtrace enabled.
(Kudos go to @looserfrog)

Thanks for finding that thread @boehle and cross-posting the information to this thread. I think this will help some people with this problem.

FWIW I'm fairly confident that in my coworker's case above, he wasn't running Avira: The antivirus software we use at my company is automatically set up by IT. Whatever antivirus softare we were using at the time would have been used by everyone else, too. I don't remember what software it was at the time.

@cjlarose no worries :). Yeah I hope, it might help others too.

I suspect if Avira is blocking /dev devices, other anti virus software might do the same. So it might just be running anti virus software in general with maybe a specific config, blocking those /dev devices dtrace needs access to.

I was able to get this working by applying the following changes to the Makefile:

186c186
< DTRACE        = dtrace -xnolibs
---
> DTRACE        = /usr/bin/sudo /usr/sbin/dtrace -xnolibs
394a395
>   $(Q) /usr/bin/sudo /usr/sbin/chown $$(whoami):$$(id -g -n) $@
Was this page helpful?
0 / 5 - 0 ratings