This is the mail archive of the gdb@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

MT program receives SIGSEGV while debugging remotely


Hi all,

I'm using gdb/gdbserver 6.0 (built on RH 8.0 (glibc 2.2.93-5))
for debugging my multithreaded application remotely on x86
target and run into this.

I double-checked the libraries used in program build and
located on target.
Finally I reproduced it on the RH 8 host running
fresh-built gdb/gdbserver. The behaviour is the same for
dynamically and statically linked program.

The testcase is pretty simple: main() creates 2 threads,
each doing nothing but printf(). After last pthread_create()
main() orders a SIGALRM with sigaction(), calls alarm(6)
and sleeps in sigsuspend() waiting for it.

I set the breakpoint in thread and it triggered OK.
Then I got SIGSEGV trying to 'next':

GNU gdb 6.0
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x40000b30 in ?? ()
(gdb) b foo
Breakpoint 1 at 0x80485f8: file /tmp/cvarmut.c, line 35.
(gdb) c
Continuing.
[New Thread 8192]
[New Thread 8194]
[Switching to Thread 8194]


Breakpoint 1, foo (str=0x804886c "+") at /tmp/cvarmut.c:35
35        printf("%s", str);
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x080485f9 in foo (str=0x804886c "+") at /tmp/cvarmut.c:35
35        printf("%s", str);
(gdb)



Debugging natively goes OK, as well as the program runnig itself.

Probably this is fixed already but unfortunately I've found no
mentions about such a bug since gdb 6.0 was released.
Thanks in advance for any help...
(I'm attaching the test progarm for convenience.)

-Sergei
// INCLUDE FILES
#include <stdio.h>      // Standard I/O defines for printf, etc.
#include <stdlib.h>     // Defines EXIT_SUCCESS and EXIT_FAILURE
#include <pthread.h>    // Headers for thread creation and access
#include <unistd.h>     // Misc. POSIX defines, like sleep()
#include <signal.h>		// Signal handling datatypes and routines

// Defines
#define TIME_LIMIT 6    /* Timer time limit */

// Global Variable Declarations
  static pthread_t tid1, tid2;    	// Variable to hold ids of threads
  static pthread_attr_t t_attr;   	// Attribute creation structure
  static pthread_mutex_t mut;     	// Variable to hold reference to mutex
  static pthread_mutexattr_t mut_attr; 	// Mutex attribute creation struct
  static pthread_cond_t cv_a, cv_b;    	// Variable to hold condition vars
  static pthread_condattr_t cv_attr;   	// Cond var attr creation struct

static int cv_count = 0; // Variable to keep track of execution cycles
int got_alarm = 0;

// Alarm handler for SIGALRM. This prints out the final 
// results and terminates the program and its respective threads.

void sig_alarm_handler(int sig, void *x)
{
    fprintf(stderr, "Benchmark results: %d cycles per second\n",
        cv_count / TIME_LIMIT);
    got_alarm = 1;
}

void foo(char *str)
{
  printf("%s", str);
}


void *thread1(void *seq)
{
  int i;
    for (;; cv_count++) {   // Run till stopped from the outside.
      i = 100000;
      foo("+");
      while (i--)
	;
    }
    return 0;
}

// Code for thread 2. Slightly different from that of 
// thread 1 in that it sets the data structure values 
// a differently.

void *thread2(void *seq)
{
  int i;
  for (;; cv_count++) {   // Run until stopped by signal
    i = 100000;
    foo("-");
    while(i--)
      ;
  }
  return 0;
}

//////////////////////////////////////////////////////////////////////////
// main	entry point to demo_cvarmut
int  main() {

    struct sigaction act;   // Used to hold signal mask and flags
    sigset_t set;           // Signal Receipt method mask

  
    // Create thread attribute structure.
    if (pthread_attr_init(&t_attr) == -1) {
        perror("pthread_attr_init");
        exit(EXIT_FAILURE);
    }

    // Create thread 1.
    if (pthread_create(&tid1, &t_attr, thread1, 0) == -1) {
        perror("pthread_create(1)");
        exit(EXIT_FAILURE);
    }

    // Create thread 2.
    if (pthread_create(&tid2, &t_attr, thread2, 0) == -1) {
        perror("pthread_create(2)");
        exit(EXIT_FAILURE);
    }

    // cast suppresses warning for g++
    act.sa_handler = (void(*))sig_alarm_handler; // Handler for timer sig.
    sigemptyset(&act.sa_mask);      // Default signal receipt method.
    act.sa_flags = 0;               // Clear signal mask.
    
    //  Set the SIGALRM signal to execute sig_alarm_handler upon receipt of SIGALRM.
    if (sigaction(SIGALRM, &act, (struct sigaction *) NULL)) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }

    alarm(TIME_LIMIT);  // Set SIGALRM to trigger in TIME_LIMIT secs.

    //  Clear POSIX-compliant signal mask. All signals can 
    //  interrupt. Note that this is slightly more complicated 
    //  than our standard pause() call, but it illustrates the 
    //  use of the POSIX signal mask which is actually 64 
    //  bits long.  (32 for signals and 32 for events).

    sigemptyset(&set);  

    // Loop, waiting for signals to arrive. Program termination 
    // is accomplished through SIGALRM signal or through 
    // default action of terminating signals like SIGINT...
    printf("Threads created, now loop waiting for signals\n");
    for (;;) {
        sigsuspend(&set);
        if (got_alarm == 1){
          return 0;
        }
    }
    return 0;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]