Consider a gdb_load patch to call the gdb_file_cmd twice:
...
 proc gdb_load { arg } {
     if { $arg != "" } {
+       set res [gdb_file_cmd $arg]
+       if { $res != 0 } {
+           return $res
+       }
        return [gdb_file_cmd $arg]
     }
     return 0
 }
...
When running test-case gdb.base/index-cache.exp, we run into:
...
ERROR: Couldn't load outputs/gdb.base/index-cache/index-cache, other program \
  already loaded (timeout).
FAIL: gdb.base/index-cache.exp: test_cache_enabled_miss: check index-cache \
  stats (GDB internal error)
ERROR: Couldn't load outputs/gdb.base/index-cache/index-cache, other program \
  already loaded (timeout).
...
The first timeout in more detail:
...
(gdb) file outputs/gdb.base/index-cache/index-cache^M
Load new symbol table from "index-cache"? (y or n) y^M
Reading symbols from index-cache...^M
src/gdb/dwarf2/read.c:2540: internal-error: \
  void create_cus_from_index(dwarf2_per_bfd*, const gdb_byte*, offset_type, \
                             const gdb_byte*, offset_type): \
  Assertion `per_bfd->all_comp_units.empty ()' failed.^M
A problem internal to GDB has been detected,^M
further debugging may prove unreliable.^M
Quit this debugging session? (y or n) ERROR: Couldn't load index-cache, \
  other program already loaded (timeout).
...
Proc gdb_file_cmd has a gdb_expect handling the result of the file command,
and if the result is a "Load new symbol table from index-cache? (y or n) "
prompt, it sends a "y" and enters in a nested gdb_expect to handle the
result.
The first gdb_expect contains code to handle "A problem internal to GDB has
been detected", but the second one doesn't, which causes the timeout.
Fix this by removing the nested gdb_expect, and using exp_continue instead,
such that we have instead:
...
ERROR: Couldn't load outputs/gdb.base/index-cache/index-cache -- with new \
  symbol table into gdb (GDB internal error).
ERROR: Couldn't load outputs/gdb.base/index-cache/index-cache -- with new \
  symbol table into gdb (GDB internal error).
...
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2020-06-04  Tom de Vries  <tdevries@suse.de>
	* lib/gdb.exp (gdb_file_cmd): Replace incomplete gdb_expect by
	exp_continue.
+2020-06-04  Tom de Vries  <tdevries@suse.de>
+
+       * lib/gdb.exp (gdb_file_cmd): Replace incomplete gdb_expect by
+       exp_continue.
+
 2020-06-04  Tom de Vries  <tdevries@suse.de>
 
        * lib/gdb.exp (gdb_file_cmd): Use perror instead of fail.
 
     }
 
     send_gdb "file $arg\n"
+    set new_symbol_table 0
     gdb_expect 120 {
        -re "Reading symbols from.*LZMA support was disabled.*$gdb_prompt $" {
            verbose "\t\tLoaded $arg into $GDB; .gnu_debugdata found but no LZMA available"
            return 0
         }
         -re "Load new symbol table from \".*\".*y or n. $" {
+           if { $new_symbol_table > 0 } {
+               perror "Couldn't load $arg, interactive prompt loop detected."
+               return -1
+           }
             send_gdb "y\n" answer
-            gdb_expect 120 {
-                -re "Reading symbols from.*$gdb_prompt $" {
-                    verbose "\t\tLoaded $arg with new symbol table into $GDB"
-                   set gdb_file_cmd_debug_info "debug"
-                   return 0
-                }
-                timeout {
-                    perror "Couldn't load $arg, other program already loaded (timeout)."
-                   return -1
-                }
-               eof {
-                   perror "Couldn't load $arg, other program already loaded (eof)."
-                   return -1
-               }
-            }
+           incr new_symbol_table
+           set arg "$arg -- with new symbol table"
+           exp_continue
        }
         -re "No such file or directory.*$gdb_prompt $" {
             perror "($arg) No such file or directory"