# File src/ruby_supportlib/phusion_passenger/preloader_shared_helpers.rb, line 98
    def run_main_loop(options)
      $0 = "Passenger AppPreloader: #{options['app_root']}"
      client = nil
      original_pid = Process.pid

      if defined?(NativeSupport)
        unix_path_max = NativeSupport::UNIX_PATH_MAX
      else
        unix_path_max = options.fetch('UNIX_PATH_MAX', 100).to_i
      end
      if options['socket_dir']
        socket_dir = options['socket_dir']
        socket_prefix = "preloader"
      else
        socket_dir = Dir.tmpdir
        socket_prefix = "PsgPreloader"
      end

      socket_filename = nil
      server = nil
      Utils.retry_at_most(128, Errno::EADDRINUSE) do
        socket_filename = "#{socket_dir}/#{socket_prefix}.#{rand(0xFFFFFFFF).to_s(36)}"
        socket_filename = socket_filename.slice(0, unix_path_max - 10)
        server = UNIXServer.new(socket_filename)
      end
      server.close_on_exec!
      File.chmod(0600, socket_filename)

      # Update the dump information just before telling the preloader that we're
      # ready because the Passenger core will read and memorize this information.
      LoaderSharedHelpers.dump_all_information(options)

      puts "!> Ready"
      puts "!> socket: unix:#{socket_filename}"
      puts "!> "

      while true
        # We call ::select just in case someone overwrites the global select()
        # function by including ActionView::Helpers in the wrong place.
        # https://code.google.com/p/phusion-passenger/issues/detail?id=915
        ios = Kernel.select([server, STDIN])[0]
        if ios.include?(server)
          result, client = accept_and_process_next_client(server)
          if result == :forked
            STDIN.reopen(client)
            STDOUT.reopen(client)
            STDOUT.sync = true
            client.close
            return :forked
          end
        end
        if ios.include?(STDIN)
          if STDIN.tty?
            begin
              # Prevent bash from exiting when we press Ctrl-D.
              STDIN.read_nonblock(1)
            rescue Errno::EAGAIN
              # Do nothing.
            end
          end
          break
        end
      end
      return nil
    ensure
      server.close if server
      if original_pid == Process.pid
        File.unlink(socket_filename) rescue nil
      end
    end