aboutsummaryrefslogtreecommitdiff
path: root/gdb/sol-thread.c
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@vmware.com>1997-05-21 23:33:33 +0000
committerMichael Snyder <msnyder@vmware.com>1997-05-21 23:33:33 +0000
commit3780c3370815a315927580bcd22ce5e361cc9950 (patch)
treece084be089ac9adc56a4618d34d20c6c5cb333a2 /gdb/sol-thread.c
parentb4a4a6dc0f47fb30af11d0b636014b6edced417f (diff)
downloadgdb-3780c3370815a315927580bcd22ce5e361cc9950.zip
gdb-3780c3370815a315927580bcd22ce5e361cc9950.tar.gz
gdb-3780c3370815a315927580bcd22ce5e361cc9950.tar.bz2
Wed May 21 16:03:25 1997 Michael Snyder <msnyder@cleaver.cygnus.com>
* procfs.c (init_procinfo): new function, abstracts some code shared by create_procinfo and do_attach; (procfs_set_inferior_syscall_traps): new function, abstracts some code needed by procfs_init_inferior, do_attach, and procfs_lwp_creation_handler; (procfs_first_available): new function, find any LWP that's runnable; (procfs_thread_alive): replace stub function with real implementation; (procfs_lwp_creation_handler): fix bug starting new child threads; (info_proc): bug fixes and enhancements for the "INFO PROCESSES" command; (close_procinfo_file): call new function "delete_thread" to cleanup GDB's thread database; (proc_init_failed): add new argument "kill", to control whether process is killed (so this function can be shared by create_procinfo and do_attach); (procfs_exit_handler): handle exit from an attached process, and cleanup procinfo handles when the process exits; (procfs_resume, procfs_wait): cleanup after a thread when it exits; (do_attach, do_detach): handle attached processes with multiple threads; plus some general improvements in the diagnostic output. * sol-thread.c (sol_thread_alive): replace stub with real implementation; (thread_to_lwp, lwp_to_thread): enhance to handle threads that may have exited; (sol_thread_attach): add startup setup stuff; (sol_thread_detach): add unpush_target call; (sol_thread_mourn_inferior): add unpush_target call; (sol_thread_wait, sol_thread_resume): enhance to deal with thread exit cleanly; (sol_thread_new_objfile, sol_thread_pid_to_str): detect unsuccessful startup and don't crash; plus some general cleanup. * thread.c (delete_thread): new function, allows targets to notify gdb when a thread is no longer valid. * infrun.c (wait_for_inferior): don't try to detect a new thread on receiving a TARGET_EXITED event.
Diffstat (limited to 'gdb/sol-thread.c')
-rw-r--r--gdb/sol-thread.c167
1 files changed, 124 insertions, 43 deletions
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 00bdc60..4b73c19 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -72,6 +72,7 @@ extern struct target_ops sol_thread_ops; /* Forward declaration */
extern int procfs_suppress_run;
extern struct target_ops procfs_ops; /* target vector for procfs.c */
+extern char *procfs_pid_to_str PARAMS ((int pid));
/* Note that these prototypes differ slightly from those used in procfs.c
for of two reasons. One, we can't use gregset_t, as that's got a whole
@@ -110,10 +111,11 @@ static struct cleanup * save_inferior_pid PARAMS ((void));
static void restore_inferior_pid PARAMS ((int pid));
static char *td_err_string PARAMS ((td_err_e errcode));
static char *td_state_string PARAMS ((td_thr_state_e statecode));
-static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
+static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
static void sol_thread_resume PARAMS ((int pid, int step,
enum target_signal signo));
static int lwp_to_thread PARAMS ((int lwp));
+static int sol_thread_alive PARAMS ((int pid));
#define THREAD_FLAG 0x80000000
#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
@@ -306,24 +308,22 @@ thread_to_lwp (thread_id, default_lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
- int pid;
- int lwp;
if (is_lwp (thread_id))
return thread_id; /* It's already an LWP id */
/* It's a thread. Convert to lwp */
- pid = PIDGET (thread_id);
- thread_id = GET_THREAD(thread_id);
-
- val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
- if (val != TD_OK)
+ val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
val = p_td_thr_get_info (&th, &ti);
-
- if (val != TD_OK)
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
if (ti.ti_state != TD_THR_ACTIVE)
@@ -333,10 +333,8 @@ thread_to_lwp (thread_id, default_lwp)
error ("thread_to_lwp: thread state not active: %s",
td_state_string (ti.ti_state));
}
-
- lwp = BUILD_LWP (ti.ti_lid, pid);
- return lwp;
+ return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
}
/*
@@ -367,29 +365,34 @@ lwp_to_thread (lwp)
td_thrinfo_t ti;
td_thrhandle_t th;
td_err_e val;
- int pid;
- int thread_id;
if (is_thread (lwp))
return lwp; /* It's already a thread id */
/* It's an lwp. Convert it to a thread id. */
- pid = PIDGET (lwp);
- lwp = GET_LWP (lwp);
+ if (!sol_thread_alive (lwp))
+ return -1; /* defunct lwp */
- val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
- if (val != TD_OK)
+ val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
- val = p_td_thr_get_info (&th, &ti);
+ val = p_td_thr_validate (&th);
+ if (val == TD_NOTHR)
+ return lwp; /* libthread doesn't know about it, just return lwp */
+ else if (val != TD_OK)
+ error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
- if (val != TD_OK)
+ val = p_td_thr_get_info (&th, &ti);
+ if (val == TD_NOTHR)
+ return -1; /* thread must have terminated */
+ else if (val != TD_OK)
error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
- thread_id = BUILD_THREAD (ti.ti_tid, pid);
-
- return thread_id;
+ return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
}
/*
@@ -456,7 +459,19 @@ sol_thread_attach (args, from_tty)
int from_tty;
{
procfs_ops.to_attach (args, from_tty);
-
+ /* Must get symbols from solibs before libthread_db can run! */
+ SOLIB_ADD ((char *)0, from_tty, (struct target_ops *)0);
+ if (sol_thread_active)
+ {
+ printf_filtered ("sol-thread active.\n");
+ main_ph.pid = inferior_pid; /* Save for xfer_memory */
+ push_target (&sol_thread_ops);
+ inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
+ else
+ add_thread (inferior_pid);
+ }
/* XXX - might want to iterate over all the threads and register them. */
}
@@ -473,6 +488,7 @@ sol_thread_detach (args, from_tty)
char *args;
int from_tty;
{
+ unpush_target (&sol_thread_ops);
procfs_ops.to_detach (args, from_tty);
}
@@ -492,12 +508,19 @@ sol_thread_resume (pid, step, signo)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
if (pid != -1)
{
+ int save_pid = pid;
+
pid = thread_to_lwp (pid, -2);
if (pid == -2) /* Inactive thread */
error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
}
procfs_ops.to_resume (pid, step, signo);
@@ -521,28 +544,44 @@ sol_thread_wait (pid, ourstatus)
old_chain = save_inferior_pid ();
inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
+ if (inferior_pid == -1)
+ inferior_pid = procfs_first_available ();
if (pid != -1)
- pid = thread_to_lwp (pid, -1);
+ {
+ int save_pid = pid;
+
+ pid = thread_to_lwp (pid, -2);
+ if (pid == -2) /* Inactive thread */
+ error ("This version of Solaris can't start inactive threads.");
+ if (info_verbose && pid == -1)
+ warning ("Specified thread %d seems to have terminated",
+ GET_THREAD (save_pid));
+ }
rtnval = procfs_ops.to_wait (pid, ourstatus);
- if (rtnval != save_pid
- && !in_thread_list (rtnval))
+ if (ourstatus->kind != TARGET_WAITKIND_EXITED)
{
- fprintf_unfiltered (gdb_stderr, "[New %s]\n",
- target_pid_to_str (rtnval));
- add_thread (rtnval);
+ /* Map the LWP of interest back to the appropriate thread ID */
+ rtnval = lwp_to_thread (rtnval);
+ if (rtnval == -1)
+ rtnval = save_pid;
+
+ /* See if we have a new thread */
+ if (is_thread (rtnval)
+ && rtnval != save_pid
+ && !in_thread_list (rtnval))
+ {
+ printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
+ add_thread (rtnval);
+ }
}
/* During process initialization, we may get here without the thread package
being initialized, since that can only happen after we've found the shared
libs. */
- /* Map the LWP of interest back to the appropriate thread ID */
-
- rtnval = lwp_to_thread (rtnval);
-
do_cleanups (old_chain);
return rtnval;
@@ -751,8 +790,6 @@ sol_thread_notice_signals (pid)
procfs_ops.to_notice_signals (pid);
}
-void target_new_objfile PARAMS ((struct objfile *objfile));
-
/* Fork an inferior process, and start debugging it with /proc. */
static void
@@ -763,13 +800,15 @@ sol_thread_create_inferior (exec_file, allargs, env)
{
procfs_ops.to_create_inferior (exec_file, allargs, env);
- if (sol_thread_active)
+ if (sol_thread_active && inferior_pid != 0)
{
main_ph.pid = inferior_pid; /* Save for xfer_memory */
push_target (&sol_thread_ops);
inferior_pid = lwp_to_thread (inferior_pid);
+ if (inferior_pid == -1)
+ inferior_pid = main_ph.pid;
add_thread (inferior_pid);
}
@@ -794,6 +833,10 @@ sol_thread_new_objfile (objfile)
return;
}
+ /* don't do anything if init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return;
+
/* Now, initialize the thread debugging library. This needs to be done after
the shared libraries are located because it needs information from the
user's thread library. */
@@ -816,6 +859,7 @@ sol_thread_new_objfile (objfile)
static void
sol_thread_mourn_inferior ()
{
+ unpush_target (&sol_thread_ops);
procfs_ops.to_mourn_inferior ();
}
@@ -827,11 +871,40 @@ sol_thread_can_run ()
return procfs_suppress_run;
}
+/*
+
+LOCAL FUNCTION
+
+ sol_thread_alive - test thread for "aliveness"
+
+SYNOPSIS
+
+ static bool sol_thread_alive (int pid);
+
+DESCRIPTION
+
+ returns true if thread still active in inferior.
+
+ */
+
static int
sol_thread_alive (pid)
int pid;
{
- return 1;
+ if (is_thread (pid)) /* non-kernel thread */
+ {
+ td_err_e val;
+ td_thrhandle_t th;
+
+ pid = GET_THREAD (pid);
+ if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
+ return 0; /* thread not found */
+ if ((val = p_td_thr_validate (&th)) != TD_OK)
+ return 0; /* thread not valid */
+ return 1; /* known thread: return true */
+ }
+ else /* kernel thread (LWP): let procfs test it */
+ return procfs_ops.to_thread_alive (pid);
}
static void
@@ -910,9 +983,9 @@ rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
if (cc < 0)
{
if (dowrite == 0)
- print_sys_errmsg ("ps_pdread (): read", errno);
+ print_sys_errmsg ("rw_common (): read", errno);
else
- print_sys_errmsg ("ps_pdread (): write", errno);
+ print_sys_errmsg ("rw_common (): write", errno);
do_cleanups (old_chain);
@@ -1123,19 +1196,27 @@ solaris_pid_to_str (pid)
{
static char buf[100];
+ /* in case init failed to resolve the libthread_db library */
+ if (!procfs_suppress_run)
+ return procfs_pid_to_str (pid);
+
if (is_thread (pid))
{
int lwp;
lwp = thread_to_lwp (pid, -2);
- if (lwp != -2)
+ if (lwp == -1)
+ sprintf (buf, "Thread %d (defunct)", GET_THREAD (pid));
+ else if (lwp != -2)
sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
else
sprintf (buf, "Thread %d ", GET_THREAD (pid));
}
- else
+ else if (GET_LWP (pid) != 0)
sprintf (buf, "LWP %d ", GET_LWP (pid));
+ else
+ sprintf (buf, "process %d ", PIDGET (pid));
return buf;
}