[gdb/testsuite] Work around tcl bug in libsegfault.exp with check-read1
authorTom de Vries <tdevries@suse.de>
Tue, 30 Jul 2019 14:15:46 +0000 (16:15 +0200)
committerTom de Vries <tdevries@suse.de>
Tue, 30 Jul 2019 14:15:46 +0000 (16:15 +0200)
When running libsegfault.exp with check-read1, I get:
...
Running gdb/testsuite/gdb.base/libsegfault.exp ...
ERROR: tcl error sourcing gdb/testsuite/gdb.base/libsegfault.exp.
ERROR: no such variable
    (read trace on "env(LD_PRELOAD)")
    invoked from within
"set env(LD_PRELOAD)"
    ("uplevel" body line 1)
    invoked from within
"uplevel 1 [list set $var]"
    invoked from within
"if [uplevel 1 [list array exists $var]] {
                set saved_arrays($var) [uplevel 1 [list array get $var]]
            } else {
                set saved_scalars($var) [uplevel ..."
    invoked from within
"if [uplevel 1 [list info exists $var]] {
            if [uplevel 1 [list array exists $var]] {
                set saved_arrays($var) [uplevel 1 [list array get $var]]
          ..."
    (procedure "save_vars" line 11)
    invoked from within
"save_vars { env(LD_PRELOAD) } {
        if { ![info exists env(LD_PRELOAD) ]
             || $env(LD_PRELOAD) == "" } {
            set env(LD_PRELOAD) "$lib"
        } else {
         ..."
    (procedure "gdb_spawn_with_ld_preload" line 4)
    invoked from within
"gdb_spawn_with_ld_preload $libsegfault """
...

There are several things here interacting with environment variable
LD_PRELOAD:
- the expect "binary" build/gdb/testsuite/expect-read1 with does
  export LD_PRELOAD=build/gdb/testsuite/read1.so before calling native expect
- read1.so which does unsetenv ("LD_PRELOAD") upon first call to read
- the test-case, which wants to set or append libSegFault.so to LD_PRELOAD

The error occurs when accessing $env(LD_PRELOAD), in a branch where
"info exists env(LD_PRELOAD)" returns true. AFAIU, this is
https://core.tcl-lang.org/tcl/tktview?name=67fd4f973a "incorrect results of
'info exists' when unset env var in one interp and check for existence from
another interp".

Work around the tcl bug by not unsetting the variable, but setting it to ""
instead:
...
-      unsetenv ("LD_PRELOAD");
+      setenv ("LD_PRELOAD", "", 1);
...

Verified that reverting commit de28a3b72e "[gdb/testsuite, 2/2] Fix
gdb.linespec/explicit.exp with check-read1" reintroduced the check-read1
failure in gdb.linespec/explicit.exp.

This fixes a similar error in attach-slow-waitpid.exp, which also sets
LD_PRELOAD.

Tested on x86_64-linux with check-read1.

gdb/testsuite/ChangeLog:

2019-07-30  Tom de Vries  <tdevries@suse.de>

* lib/read1.c (read): Don't use unsetenv (v), use setenv (v, "", 1)
instead.

gdb/testsuite/ChangeLog
gdb/testsuite/lib/read1.c

index 3476d7f46f27d3bd73e10e03e86ce481f15127be..0bf6be994e4c744ecece6070847b283b1028ad1b 100644 (file)
@@ -1,3 +1,8 @@
+2019-07-30  Tom de Vries  <tdevries@suse.de>
+
+       * lib/read1.c (read): Don't use unsetenv (v), use setenv (v, "", 1)
+       instead.
+
 2019-07-30  Tom de Vries  <tdevries@suse.de>
 
        PR testsuite/24834
index 0547661346903a59c52dab9990bf5d44c9310eb1..bee0945543ef825eda030e3df97cb32ebd7b585b 100644 (file)
@@ -31,7 +31,11 @@ read (int fd, void *buf, size_t count)
   static ssize_t (*read2) (int fd, void *buf, size_t count) = NULL;
   if (read2 == NULL)
     {
-      unsetenv ("LD_PRELOAD");
+      /* Use setenv (v, "", 1) rather than unsetenv (v) to work around
+         https://core.tcl-lang.org/tcl/tktview?name=67fd4f973a "incorrect
+        results of 'info exists' when unset env var in one interp and check
+        for existence from another interp".  */
+      setenv ("LD_PRELOAD", "", 1);
       read2 = dlsym (RTLD_NEXT, "read");
     }
   if (count > 1 && isatty (fd) >= 1)