# File lib/phusion_passenger/preloader_shared_helpers.rb, line 97
        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['generation_dir']
                        socket_dir = "#{options['generation_dir']}/backends"
                        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 HelperAgent will read and memorize this information.
                LoaderSharedHelpers.dump_all_information

                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