Break it Baby, break it - How the network sniffer "Wireshark" can break Rubygems
Image credit: DALL-EOccasionally I get some really weird errors when I try to install gems using gem
or bundler. It took me some time to find out the reason for this. Read on if
you’d like to hear the full story.
Installation of rubygem “unf_ext” failed
In most cases those errors occur after an upgrade of ruby. To give you an
example, read the following error message from installing the unf_ext-gem.
After reading the message the first time, my first guess was a missing library
stdc++.
# Version of Rubygems
gem -v
# => 2.4.5.1
# Install the gem
gem install unf_ext -v 0.0.7.1
# => Building native extensions. This could take a while...
# => ERROR: Error installing unf_ext:
# => ERROR: Failed to build gem native extension.
# =>
# => /usr/bin/ruby -r ./siteconf20151030-29963-guv2om.rb extconf.rb
# => checking for main() in -lstdc++... *** extconf.rb failed ***
# => Could not create Makefile due to some reason, probably lack of necessary
# => libraries and/or headers. Check the mkmf.log file for more details. You may
# => need configuration options.
# =>
# => Provided configuration options:
# => --with-opt-dir
# => --without-opt-dir
# => --with-opt-include
# => --without-opt-include=${opt-dir}/include
# => --with-opt-lib
# => --without-opt-lib=${opt-dir}/lib
# => --with-make-prog
# => --without-make-prog
# => --srcdir=.
# => --curdir
# => --ruby=/usr/bin/$(RUBY_BASE_NAME)
# => --with-static-libstdc++
# => --without-static-libstdc++
# => --with-stdc++lib
# => --without-stdc++lib
# => /usr/lib/ruby/2.2.0/mkmf.rb:456:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
# => You have to install development tools first.
# => from /usr/lib/ruby/2.2.0/mkmf.rb:541:in `try_link0'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:556:in `try_link'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:735:in `try_func'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:966:in `block in have_library'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:911:in `block in checking_for'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:351:in `block (2 levels) in postpone'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:321:in `open'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:351:in `block in postpone'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:321:in `open'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:347:in `postpone'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:910:in `checking_for'
# => from /usr/lib/ruby/2.2.0/mkmf.rb:961:in `have_library'
# => from extconf.rb:6:in `<main>'
# =>
# => extconf failed, exit code 1
# =>
# => Gem files will remain installed in /home/user/.gem/ruby/2.2.3/gems/unf_ext-0.0.7.1 for inspection.
# => Results logged to /home/user/.gem/ruby/2.2.3/extensions/x86_64-linux/2.2.0/unf_ext-0.0.7.1/gem_make.out
Checking if the required library is available
At first I tried to locate the missing library – I could also have used
find instead: Everything looked good, the library exists on my system. So I
moved on and tried strace to see what file the compiler looks for.
# make sure the db of locate is up to date
updatedb
# locate the library
locate -b "stdc++"
# => [...]
# => /usr/lib/libstdc++.a
# => /usr/lib/libstdc++.so
# => /usr/lib/libstdc++.so.6
# => /usr/lib/libstdc++.so.6.0.20
# => [...]
Checking which files the compiler looks for
To find out which files are involved in some error, I normally use strace,
especially if I get “Permissions Denied” errors for no obvious reason. I reduce
the output, I chose to filter out any non-file “syscall”.
strace -e trace=file gem install unf_ext
This command outputs its findings to STDOUT by default. But it was far too much
information for STDOUT, so I wanted to save them to the hard disk at
/tmp/output.txt …
strace -e trace=file -o /tmp/output.txt gem install unf_ext
… but when I opened the file using less, it was empty. Strange!
less /tmp/output.txt
After that I checked its size. Mmmh… 0 bytes. That’s even stranger.
ls -al /tmp/output.txt
# => -rw-r--r-- 1 user user 0 Oct 30 07:28 /tmp/output.txt
Checking available space in filesystem
Following my gut instinct, I used df to see what the usage of the
file systems look like. Ok, /tmp/ has a usage of 100%. That’s definitely not
good.
df -h
# => Filesystem Size Used Avail Use% Mounted on
# =>
# => [...]
# => tmpfs 2.0G 2.0G 0 100% /tmp
# => [...]
But why is all that space used? I had a look at /tmp/ with ls. Damn!
There’s a temporary file using all space in /tmp. Looking at it’s file name
it seems to be used by “Wireshark”. For all of you who don’t know “Wireshark”.
It’s an open source network sniffer, the successor of “Ethereal”. I use it
quite a lot to troubleshoot network issues.
ls -al /tmp/
# => [...]
# => -rw-r--r-- 1 user user 2007171072 Oct 30 07:27 /tmp/wireshark_pcapng_any_20151007191347_q6LGpN
# => [...]
The file I saw is a temporary one, used by “Wireshark” to save all captured
network traffic during a live capture. Now we’ve got two options: Looking for
the “Wireshark”-window and close the program or kill it.
Cleanup file system
Closing “Wireshark” via “File > Close” makes “Wireshark” deleting its temporary
files automatically. If you kill it, you need to remove the file in
/tmp manually. Therefor I decided to close “Wireshark” regularly. When I
checked the file system usage, only 4% was used by some smaller files.
df -h
# => [...]
# => tmpfs 2.0G 65M 1.9G 4% /tmp
# => [...]
Installing the gem again
After /tmp/ had been cleaned up, the installation of the “unf_ext”-gem was a
success.
gem install unf_ext
# => Building native extensions. This could take a while...
# => Successfully installed unf_ext-0.0.7.1
# => 1 gem installed
Conclusion
Ok. I must be honest: In most cases I forgot that I ran wireshark in the
background and it filled up my /tmp/-directory. There might be other programs
as well, which fill up your /tmp-directory. A usage 100% can break “Rubygems”
and other programs which use /tmp to store temporary files. Even docker
uses it, to store temporary trusted-docker-files during a build-run. So be
careful not fill it up to much.
Thanks for reading!