Contributing a thread fork testcase for AIX.

Message ID 20240517085055.95478-1-akamath996@gmail.com
State New
Headers
Series Contributing a thread fork testcase for AIX. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed

Commit Message

Aditya Vidyadhar Kamath May 17, 2024, 8:50 a.m. UTC
  From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>

This test case tests if a child process created by a parent thread fork
does not segment fault like in the commit https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=414aa6987f21a814851e5f3113388a3616993fa3

This test case also tests if the shared library is loaded properly for the child process.
One example of why this is required is this commit https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=7a2a5ff865bead782393897fc5fde47def30dad4

where BFD file name for shared
library members was changed when the library was loaded
for the first time, which caused the library to no longer
be recognized by name when loaded a second time.

The test expects the GDB output to be as below in AIX:
(gdb) set print thread-events on
(gdb) set detach-on-fork off
(gdb) set follow-fork-mode child
(gdb) delete breakpoints
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb) break -qualified main
Breakpoint 1 at 0x100009a8: file /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c, line 65.
(gdb) run
Starting program: /current_gdb/binutils-gdb/gdb/testsuite/outputs/gdb.threads/thread_info_shared/thread_info_shared

Breakpoint 1, main () at /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c:65
65        alarm (300);
(gdb) break Do_nothing
Breakpoint 2 at 0x10000089c: file /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c, line 32.
(gdb) c
Continuing.
[New Thread 258 (tid 67438637)]
[Attaching after Thread 258 (tid 67438637) fork to child process 14287164]
[New inferior 2 (process 14287164)]
Hello from Child!
[Switching to Thread 258 (tid 68094177)]

Thread 2.1 hit Breakpoint 2.2, Do_nothing () at /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c:32
32      }
(gdb) info sharedlibrary /usr/lib/libcrypt.a
From                To                  Syms Read   Shared Object Library
0x0900000000695420  0x0900000000695c9e  Yes (*)     /usr/lib/libcrypt.a(shr_64.o)
(*): Shared library is missing debugging information.
(gdb) delete breakpoints
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb)
---
 .../gdb.threads/thread_info_shared.c          | 82 ++++++++++++++++++
 .../gdb.threads/thread_info_shared.exp        | 84 +++++++++++++++++++
 2 files changed, 166 insertions(+)
 create mode 100644 gdb/testsuite/gdb.threads/thread_info_shared.c
 create mode 100644 gdb/testsuite/gdb.threads/thread_info_shared.exp
  

Comments

Aditya Kamath May 17, 2024, 8:58 a.m. UTC | #1
Respected community members,

Hi,

Few things I wanted to ask is,

1: Is the copyright okay for this test case? I took it from gdb.threads/thread_events.exp file.
2: Do we need to add these files in a configure script or a make file?
3: Any changelog to be updated while contributing new files?

Kindly give me feedback for this patch and let me know if we can do this better. Also, kindly let me know about the above questions.

Have a nice day ahead.

Thanks and regards,
Aditya.

From: Aditya Vidyadhar Kamath <akamath996@gmail.com>
Date: Friday, 17 May 2024 at 2:21 PM
To: tom@tromey.com <tom@tromey.com>
Cc: Ulrich Weigand <Ulrich.Weigand@de.ibm.com>, gdb-patches@sourceware.org <gdb-patches@sourceware.org>, Aditya Kamath1 <Aditya.Kamath1@ibm.com>, Sangamesh Mallayya <sangamesh.swamy@in.ibm.com>
Subject: [EXTERNAL] [PATCH] Contributing a thread fork testcase for AIX.
From: Aditya Vidyadhar Kamath <Aditya.Kamath1@ibm.com>

This test case tests if a child process created by a parent thread fork
does not segment fault like in the commit https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff;h=414aa6987f21a814851e5f3113388a3616993fa3

This test case also tests if the shared library is loaded properly for the child process.
One example of why this is required is this commit https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=7a2a5ff865bead782393897fc5fde47def30dad4

where BFD file name for shared
library members was changed when the library was loaded
for the first time, which caused the library to no longer
be recognized by name when loaded a second time.

The test expects the GDB output to be as below in AIX:
(gdb) set print thread-events on
(gdb) set detach-on-fork off
(gdb) set follow-fork-mode child
(gdb) delete breakpoints
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb) break -qualified main
Breakpoint 1 at 0x100009a8: file /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c, line 65.
(gdb) run
Starting program: /current_gdb/binutils-gdb/gdb/testsuite/outputs/gdb.threads/thread_info_shared/thread_info_shared

Breakpoint 1, main () at /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c:65
65        alarm (300);
(gdb) break Do_nothing
Breakpoint 2 at 0x10000089c: file /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c, line 32.
(gdb) c
Continuing.
[New Thread 258 (tid 67438637)]
[Attaching after Thread 258 (tid 67438637) fork to child process 14287164]
[New inferior 2 (process 14287164)]
Hello from Child!
[Switching to Thread 258 (tid 68094177)]

Thread 2.1 hit Breakpoint 2.2, Do_nothing () at /current_gdb/binutils-gdb/gdb/testsuite/gdb.threads/thread_info_shared.c:32
32      }
(gdb) info sharedlibrary /usr/lib/libcrypt.a
From                To                  Syms Read   Shared Object Library
0x0900000000695420  0x0900000000695c9e  Yes (*)     /usr/lib/libcrypt.a(shr_64.o)
(*): Shared library is missing debugging information.
(gdb) delete breakpoints
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb)
---
 .../gdb.threads/thread_info_shared.c          | 82 ++++++++++++++++++
 .../gdb.threads/thread_info_shared.exp        | 84 +++++++++++++++++++
 2 files changed, 166 insertions(+)
 create mode 100644 gdb/testsuite/gdb.threads/thread_info_shared.c
 create mode 100644 gdb/testsuite/gdb.threads/thread_info_shared.exp

diff --git a/gdb/testsuite/gdb.threads/thread_info_shared.c b/gdb/testsuite/gdb.threads/thread_info_shared.c
new file mode 100644
index 00000000000..a78f2ffb4e6
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/thread_info_shared.c
@@ -0,0 +1,82 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/ >.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <assert.h>
+
+pthread_barrier_t barrier;
+
+#define NUM_THREADS 1
+
+void
+Do_nothing ()
+{
+  /* Does nothing.  */
+}
+
+void *
+thread_function (void *arg)
+{
+  /* This ensures that the breakpoint is only hit after both threads
+     are born.  */
+  pthread_barrier_wait (&barrier);
+
+  pid_t p;
+  p = fork();
+  if (p < 0)
+    {
+      perror("fork fail");
+      exit(1);
+    }
+  // child process because return value zero
+  else if ( p == 0)
+    printf("Hello from Child!\n");
+
+  // parent process because return value non-zero.
+  else
+    printf("Hello from Parent!\n");
+
+  Do_nothing (); /* break here.  */
+}
+
+int
+main (void)
+{
+  int i;
+
+  alarm (300);
+
+  pthread_barrier_init (&barrier, NULL, NUM_THREADS);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    {
+      pthread_t thread;
+      int res;
+
+      res = pthread_create (&thread, NULL,
+                           thread_function, NULL);
+      assert (res == 0);
+    }
+
+  while (1)
+    sleep (1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/thread_info_shared.exp b/gdb/testsuite/gdb.threads/thread_info_shared.exp
new file mode 100644
index 00000000000..94de4b1aca8
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/thread_info_shared.exp
@@ -0,0 +1,84 @@
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/ >.
+
+# This file tests if thread fork event happens correctly when we follow
+# and child's shared library is loaded correctly.
+
+# This test has been verified with AIX target, and would need
+# to be generalized to support other targets
+
+require {is_any_target "*-*-aix*"}
+
+# When using the RSP, we don't get notifications about new threads.
+# This is expected, so don't test for that.
+if {[target_info gdb_protocol] == "remote"
+    || [target_info gdb_protocol] == "extended-remote"} {
+    return
+}
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug] != "" } {
+    return -1
+}
+
+global srcdir subdir binfile srcfile
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print thread-events on"
+
+gdb_test "set detach-on-fork off"
+gdb_test "set follow-fork-mode child"
+
+if {![runto_main]} {
+   return 1
+}
+
+gdb_test "break Do_nothing" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "breakpoint at Do_nothing"
+
+set any "\[^\r\n\]*"
+
+# If the thread code is handled well we should not see any core dumps
+# Or any different patterns here.
+
+gdb_test "c" \
+      [multi_line \
+       "\\\[New Thread $any\\\]" \
+       "\\\[Attaching after Thread $any fork to child process $any\\\]" \
+       "\\\[New inferior 2 $any\\\]" \
+       "Hello from Child!" \
+       "\\\[Switching to $any\\\]" \
+       "$any" \
+       "$any" \
+       "$any" \
+       ] \
+       "Test for no seg fault after child is born."
+
+#Check if the shared library is loaded for child process.
+# If shared library is not loaded correctly, this test will fail.
+gdb_test "info sharedlibrary /usr/lib/libcrypt.a" \
+     [multi_line \
+     "From                To                  Syms Read   Shared Object Library" \
+     "0x0900000000695420  0x0900000000695c9e  Yes $any" \
+     "\\\(\\\*\\\): Shared library is missing debugging information." \
+     ] \
+     "Test if child shared library is loaded"
+
+delete_breakpoints
--
2.41.0
  

Patch

diff --git a/gdb/testsuite/gdb.threads/thread_info_shared.c b/gdb/testsuite/gdb.threads/thread_info_shared.c
new file mode 100644
index 00000000000..a78f2ffb4e6
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/thread_info_shared.c
@@ -0,0 +1,82 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015-2023 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <assert.h>
+
+pthread_barrier_t barrier;
+
+#define NUM_THREADS 1 
+
+void
+Do_nothing ()
+{
+  /* Does nothing.  */
+}
+
+void *
+thread_function (void *arg)
+{
+  /* This ensures that the breakpoint is only hit after both threads
+     are born.  */ 
+  pthread_barrier_wait (&barrier);
+
+  pid_t p;
+  p = fork();
+  if (p < 0)
+    {
+      perror("fork fail");
+      exit(1);
+    }
+  // child process because return value zero
+  else if ( p == 0)
+    printf("Hello from Child!\n");
+ 
+  // parent process because return value non-zero.
+  else
+    printf("Hello from Parent!\n");
+
+  Do_nothing (); /* break here.  */
+}
+
+int
+main (void)
+{
+  int i;
+
+  alarm (300);
+
+  pthread_barrier_init (&barrier, NULL, NUM_THREADS);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    {
+      pthread_t thread;
+      int res;
+
+      res = pthread_create (&thread, NULL,
+			    thread_function, NULL);
+      assert (res == 0);
+    }
+
+  while (1)
+    sleep (1);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/thread_info_shared.exp b/gdb/testsuite/gdb.threads/thread_info_shared.exp
new file mode 100644
index 00000000000..94de4b1aca8
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/thread_info_shared.exp
@@ -0,0 +1,84 @@ 
+# Copyright (C) 2007-2024 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file tests if thread fork event happens correctly when we follow 
+# and child's shared library is loaded correctly. 
+
+# This test has been verified with AIX target, and would need
+# to be generalized to support other targets
+
+require {is_any_target "*-*-aix*"}
+
+# When using the RSP, we don't get notifications about new threads.
+# This is expected, so don't test for that.
+if {[target_info gdb_protocol] == "remote"
+    || [target_info gdb_protocol] == "extended-remote"} {
+    return
+}
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable debug] != "" } {
+    return -1
+}
+
+global srcdir subdir binfile srcfile
+
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_test "set print thread-events on"
+
+gdb_test "set detach-on-fork off"
+gdb_test "set follow-fork-mode child"
+
+if {![runto_main]} {
+   return 1
+}
+
+gdb_test "break Do_nothing" \
+    "Breakpoint.*at.* file .*$srcfile, line.*" \
+    "breakpoint at Do_nothing"
+
+set any "\[^\r\n\]*"
+
+# If the thread code is handled well we should not see any core dumps
+# Or any different patterns here.
+
+gdb_test "c" \
+      [multi_line \
+       "\\\[New Thread $any\\\]" \
+       "\\\[Attaching after Thread $any fork to child process $any\\\]" \
+       "\\\[New inferior 2 $any\\\]" \
+       "Hello from Child!" \
+       "\\\[Switching to $any\\\]" \
+       "$any" \
+       "$any" \
+       "$any" \
+       ] \
+       "Test for no seg fault after child is born."
+
+#Check if the shared library is loaded for child process.
+# If shared library is not loaded correctly, this test will fail.
+gdb_test "info sharedlibrary /usr/lib/libcrypt.a" \
+     [multi_line \
+     "From                To                  Syms Read   Shared Object Library" \
+     "0x0900000000695420  0x0900000000695c9e  Yes $any" \
+     "\\\(\\\*\\\): Shared library is missing debugging information." \
+     ] \
+     "Test if child shared library is loaded"
+
+delete_breakpoints