vagrant-landrush / landrush

A Vagrant plugin that provides a simple DNS server for Vagrant guests
MIT License
666 stars 78 forks source link

Server fails to start due to missing Bundler temporary directories #248

Closed mgomezch closed 5 years ago

mgomezch commented 8 years ago

Executing vagrant landrush start returns immediately and prints this to the terminal:

/tmp/vagrant-mgomezch-31400/vagrant20160817-31400-19sxlod not found

A pid file is created, but the server is not executing.

Apparently, what's happening is the plugin code in lib/landrush/server.rb, at Landrush::Server::start, does this:

pid = spawn('ruby', __FILE__, port.to_s, working_dir.to_s, :chdir => working_dir.to_path, :pgroup => true)

The environment for that command contains these variables:

BUNDLE_APP_CONFIG=/tmp/vagrant-mgomezch-31400
BUNDLE_CONFIG=/tmp/vagrant-mgomezch-31400/vagrant20160817-31400-1hgtvvs1
BUNDLE_GEMFILE=/tmp/vagrant-mgomezch-31400/vagrant20160817-31400-h6dnf3

Apparently, by the time the child process starts, those directories are already gone; they’re created in Vagrant’s lib/vagrant/bundler.rb in Vagrant::Bundler::init! (abridged):

      @appconfigpath = Dir.mktmpdir("vagrant-bundle-app-config")
      @configfile = tempfile("vagrant-configfile")
      @gemfile = build_gemfile(plugins)
      Util::SafeEnv.change_env do |env|
        env["BUNDLE_APP_CONFIG"] = @appconfigpath
        env["BUNDLE_CONFIG"] = @configfile.path
        env["BUNDLE_GEMFILE"] = @gemfile.path
      end

Indeed, the Vagrant::Bundler::tempfile method considers the issue of shelling out and losing temporary files:

    # This method returns a proper "tempfile" on disk. Ruby's Tempfile class
    # would work really great for this, except GC can come along and  remove
    # the file before we are done with it. This is because we "close" the file,
    # but we might be shelling out to a subprocess.
    #
    # @return [File]
    def tempfile(name)
      path = Dir::Tmpname.create(name) {}
      return File.open(path, "w+")
    end

However, the Vagrant::Bundler::deinit method does remove them anyway (abridged):

    # Removes any temporary files created by init
    def deinit
      FileUtils.rm_rf(ENV["BUNDLE_APP_CONFIG"]) rescue nil
      FileUtils.rm_f(ENV["BUNDLE_CONFIG"]) rescue nil
      FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]) rescue nil
      FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]+".lock") rescue nil
    end

And indeed the main Vagrant executable at bin/vagrant schedules Vagrant::Bundler::deinit to be executed on exit:

  # Schedule the cleanup of things
  at_exit(&Vagrant::Bundler.instance.method(:deinit))

Thence the files are gone by the time the Landrush server attempts to start, because by then, the main Vagrant process has quit. I don’t know whether this is an oversight in the way Vagrant itself handles its temporary files (which might appear to be the case given the comments in Vagrant::Bundler::tempfile) or an incorrect expectation by Landrush of expecting to be able to shell out a Ruby interpreter with the temporary environment provided by Vagrant. This might even be a matter of timing; perhaps if the Landrush server manages to initialize before the main Vagrant process exits, it might have a chance to set itself up before the temporary files are removed.

I managed to work around this with a very very very dirty hack on the bin/vagrant installed in my system; just change the last two cited lines into this:

  # Schedule the cleanup of things
  if argv.include?("--no-cleanup") || ENV["VAGRANT_NO_CLEANUP"]
    argv.delete("--no-cleanup")
  else
    at_exit(&Vagrant::Bundler.instance.method(:deinit))
  end

and then starting the server manually with vagrant landrush start --no-cleanup. (I’m sorry!)

hferentschik commented 7 years ago

I am not sure where this error message is coming from, but I have seen strange behavior of Vagrant at times. Does this keep occurring for you? If so, which OS and Vagrant version? How did you install landrush?

Have you tried uninstalling all Vagrant plugins and then re-installing them? Sometimes it also helps to blow away your local Vagrant data under ~/vagrant.d (you will loose all your installed plugins and cached boxes!).

I am not able to re-produce this and the working directory for Landrush is the data directory for your Vagrant install - ~/vagrant.d/data/landrush. See also https://github.com/vagrant-landrush/landrush/blob/master/lib/landrush/command.rb#L11.

mgomezch commented 7 years ago

Yes, this is reproducible on my machine, running Ubuntu 16.04 and Vagrant 1.8.5 installed thus:

curl -L -O 'https://releases.hashicorp.com/vagrant/1.8.5/vagrant_1.8.5_x86_64.deb' && sudo dpkg -i 'vagrant_1.8.5_x86_64.deb'

Installed Landrush with vagrant plugin install afterwards. I did try uninstalling all Vagrant plugins and even removing ~/.vagrant.d entirely and it remained reproducible.

In any case, perhaps you’re not able to reproduce it due to the nature of the issue: there’s a race between Vagrant::Bundler::deinit removing files required by the process spawned by Landrush::Server::start. Perhaps you can cheat and trigger the bug by adding a delay to the spawned process, somehow, perhaps by invoking a shell script that first sleeps for a second and then execs into Ruby.

I’m not sure if this is relevant, but I run RVM. My rvm info:

ruby-2.3.0:

  system:
    uname:       "Linux andromeda 4.4.0-36-generic #55-Ubuntu SMP Thu Aug 11 18:01:55 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux"
    system:      "ubuntu/16.04/x86_64"
    bash:        "/bin/bash => GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)"
    zsh:         "/usr/bin/zsh => zsh 5.1.1 (x86_64-ubuntu-linux-gnu)"

  rvm:
    version:      "rvm 1.27.0 (latest) by Wayne E. Seguin <wayneeseguin@gmail.com>, Michal Papis <mpapis@gmail.com> [https://rvm.io/]"
    updated:      "2 months 2 days 6 hours 31 minutes 55 seconds ago"
    path:         "/home/mgomezch/.rvm"

  ruby:
    interpreter:  "ruby"
    version:      "2.3.0p0"
    date:         "2015-12-25"
    platform:     "x86_64-linux"
    patchlevel:   "2015-12-25 revision 53290"
    full_version: "ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]"

  homes:
    gem:          "/home/mgomezch/.rvm/gems/ruby-2.3.0"
    ruby:         "/home/mgomezch/.rvm/rubies/ruby-2.3.0"

  binaries:
    ruby:         "/home/mgomezch/.rvm/rubies/ruby-2.3.0/bin/ruby"
    irb:          "/home/mgomezch/.rvm/rubies/ruby-2.3.0/bin/irb"
    gem:          "/home/mgomezch/.rvm/rubies/ruby-2.3.0/bin/gem"
    rake:         "/home/mgomezch/.rvm/rubies/ruby-2.3.0/bin/rake"

  environment:
    PATH:         "/home/mgomezch/.rvm/gems/ruby-2.3.0/bin:/home/mgomezch/.rvm/gems/ruby-2.3.0@global/bin:/home/mgomezch/.rvm/rubies/ruby-2.3.0/bin:/home/mgomezch/.gvm/bin:/home/mgomezch/.rakudobrew/bin:/home/mgomezch/perl5/perlbrew/bin:/home/mgomezch/.pyenv/plugins/pyenv-virtualenv/shims:/home/mgomezch/.pyenv/shims:/home/mgomezch/.nix-profile/bin:/home/mgomezch/.nix-profile/sbin:/home/mgomezch/.rvm/bin:/home/mgomezch/.pyenv/bin:/home/mgomezch/.cargo/bin:/home/mgomezch/.rakudobrew/moar-nom/install/share/perl6/site/bin:/home/mgomezch/stuff/commands:/opt/idea-IC-162.1447.26/bin:/home/mgomezch/.nvm/versions/node/v6.3.0/bin:/home/mgomezch/.pyenv/plugins/pyenv-virtualenv/shims:/home/mgomezch/.pyenv/shims:/home/mgomezch/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
    GEM_HOME:     "/home/mgomezch/.rvm/gems/ruby-2.3.0"
    GEM_PATH:     "/home/mgomezch/.rvm/gems/ruby-2.3.0:/home/mgomezch/.rvm/gems/ruby-2.3.0@global"
    MY_RUBY_HOME: "/home/mgomezch/.rvm/rubies/ruby-2.3.0"
    IRBRC:        "/home/mgomezch/.rvm/rubies/ruby-2.3.0/.irbrc"
    RUBYOPT:      ""
    gemset:       ""