# File lib/posix/spawn.rb, line 193
    def fspawn(*args)
      env, argv, options = extract_process_spawn_arguments(*args)
      valid_options = [:chdir, :unsetenv_others, :pgroup]

      if badopt = options.find{ |key,val| !fd?(key) && !valid_options.include?(key) }
        raise ArgumentError, "Invalid option: #{badopt[0].inspect}"
      elsif !argv.is_a?(Array) || !argv[0].is_a?(Array) || argv[0].size != 2
        raise ArgumentError, "Invalid command name"
      end

      fork do
        begin
          # handle FD => {FD, :close, [file,mode,perms]} options
          options.each do |key, val|
            if fd?(key)
              key = fd_to_io(key)

              if fd?(val)
                val = fd_to_io(val)
                key.reopen(val)
              elsif val == :close
                if key.respond_to?(:close_on_exec=)
                  key.close_on_exec = true
                else
                  key.close
                end
              elsif val.is_a?(Array)
                file, mode_string, perms = *val
                key.reopen(File.open(file, mode_string, perms))
              end
            end
          end

          # setup child environment
          ENV.replace({}) if options[:unsetenv_others] == true
          env.each { |k, v| ENV[k] = v }

          # { :chdir => '/' } in options means change into that dir
          ::Dir.chdir(options[:chdir]) if options[:chdir]

          # { :pgroup => pgid } options
          pgroup = options[:pgroup]
          pgroup = 0 if pgroup == true
          Process::setpgid(0, pgroup) if pgroup

          # do the deed
          ::Kernel::exec(*argv)
        ensure
          exit!(127)
        end
      end
    end