/* Low level interface to ptrace, for GDB when running under Unix.
Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
- 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
- Free Software Foundation, Inc.
+ 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
+ 2009 Free Software Foundation, Inc.
This file is part of GDB.
int terminal_is_ours;
+#ifdef PROCESS_GROUP_TYPE
+static PROCESS_GROUP_TYPE
+gdb_getpgrp (void)
+{
+ int process_group = -1;
+#ifdef HAVE_TERMIOS
+ process_group = tcgetpgrp (0);
+#endif
+#ifdef HAVE_TERMIO
+ process_group = getpgrp ();
+#endif
+#ifdef HAVE_SGTTY
+ ioctl (0, TIOCGPGRP, &process_group);
+#endif
+ return process_group;
+}
+#endif
+
enum
{
yes, no, have_not_checked
if (our_ttystate != NULL)
{
gdb_has_a_terminal_flag = yes;
-#ifdef HAVE_TERMIOS
- our_process_group = tcgetpgrp (0);
-#endif
-#ifdef HAVE_TERMIO
- our_process_group = getpgrp ();
-#endif
-#ifdef HAVE_SGTTY
- ioctl (0, TIOCGPGRP, &our_process_group);
+#ifdef PROCESS_GROUP_TYPE
+ our_process_group = gdb_getpgrp ();
#endif
}
}
if (job_control)
{
+ struct inferior *inf = current_inferior ();
#ifdef HAVE_TERMIOS
result = tcsetpgrp (0, inferior_process_group);
- if (!attach_flag)
+ if (!inf->attach_flag)
OOPSY ("tcsetpgrp");
#endif
#ifdef HAVE_SGTTY
result = ioctl (0, TIOCSPGRP, &inferior_process_group);
- if (!attach_flag)
+ if (!inf->attach_flag)
OOPSY ("TIOCSPGRP");
#endif
}
if (!terminal_is_ours)
{
+ struct inferior *inf = current_inferior ();
+
#ifdef SIGTTOU
/* Ignore this signal since it will happen when we try to set the
pgrp. */
if (inferior_ttystate)
xfree (inferior_ttystate);
inferior_ttystate = serial_get_tty_state (stdin_serial);
-#ifdef HAVE_TERMIOS
- inferior_process_group = tcgetpgrp (0);
-#endif
-#ifdef HAVE_TERMIO
- inferior_process_group = getpgrp ();
-#endif
-#ifdef HAVE_SGTTY
- ioctl (0, TIOCGPGRP, &inferior_process_group);
+
+#ifdef PROCESS_GROUP_TYPE
+ if (!inf->attach_flag)
+ /* If setpgrp failed in terminal_inferior, this would give us
+ our process group instead of the inferior's. See
+ terminal_inferior for details. */
+ inferior_process_group = gdb_getpgrp ();
#endif
/* Here we used to set ICANON in our ttystate, but I believe this
inferior_thisrun_terminal = ttyname;
}
+
+/* If RESULT, assumed to be the return value from a system call, is
+ negative, print the error message indicated by errno and exit.
+ MSG should identify the operation that failed. */
+static void
+check_syscall (const char *msg, int result)
+{
+ if (result < 0)
+ {
+ print_sys_errmsg (msg, errno);
+ _exit (1);
+ }
+}
+
void
new_tty (void)
{
/* Now open the specified new terminal. */
tty = open (inferior_thisrun_terminal, O_RDWR | O_NOCTTY);
- if (tty == -1)
- {
- print_sys_errmsg (inferior_thisrun_terminal, errno);
- _exit (1);
- }
+ check_syscall (inferior_thisrun_terminal, tty);
/* Avoid use of dup2; doesn't exist on all systems. */
if (tty != 0)
{
close (0);
- dup (tty);
+ check_syscall ("dup'ing tty into fd 0", dup (tty));
}
if (tty != 1)
{
close (1);
- dup (tty);
+ check_syscall ("dup'ing tty into fd 1", dup (tty));
}
if (tty != 2)
{
close (2);
- dup (tty);
+ check_syscall ("dup'ing tty into fd 2", dup (tty));
}
+
+#ifdef TIOCSCTTY
+ /* Make tty our new controlling terminal. */
+ if (ioctl (tty, TIOCSCTTY, 0) == -1)
+ /* Mention GDB in warning because it will appear in the inferior's
+ terminal instead of GDB's. */
+ warning ("GDB: Failed to set controlling terminal: %s",
+ safe_strerror (errno));
+#endif
+
if (tty > 2)
close (tty);
#endif /* !go32 && !win32 */
error (_("Not confirmed."));
target_kill ();
- init_thread_list (); /* Destroy thread info */
-
- /* Killing off the inferior can leave us with a core file. If so,
- print the state we are left in. */
- if (target_has_stack)
+ /* If the current target interface claims there's still execution,
+ then don't mess with threads of other processes. */
+ if (!target_has_execution)
{
- printf_filtered (_("In %s,\n"), target_longname);
- print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ init_thread_list (); /* Destroy thread info */
+
+ /* Killing off the inferior can leave us with a core file. If
+ so, print the state we are left in. */
+ if (target_has_stack)
+ {
+ printf_filtered (_("In %s,\n"), target_longname);
+ print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
+ }
}
bfd_cache_close_all ();
}
void
set_sigint_trap (void)
{
- if (attach_flag || inferior_thisrun_terminal)
+ struct inferior *inf = current_inferior ();
+ if (inf->attach_flag || inferior_thisrun_terminal)
{
osig = (void (*)()) signal (SIGINT, pass_signal);
}
void
clear_sigint_trap (void)
{
- if (attach_flag || inferior_thisrun_terminal)
+ struct inferior *inf = current_inferior ();
+ if (inf->attach_flag || inferior_thisrun_terminal)
{
signal (SIGINT, osig);
}
}
\f
-#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN)
-static void (*old_sigio) ();
-
-static void
-handle_sigio (int signo)
-{
- int numfds;
- fd_set readfds;
-
- signal (SIGIO, handle_sigio);
-
- FD_ZERO (&readfds);
- FD_SET (target_activity_fd, &readfds);
- numfds = gdb_select (target_activity_fd + 1, &readfds, NULL, NULL, NULL);
- if (numfds >= 0 && FD_ISSET (target_activity_fd, &readfds))
- {
-#ifndef _WIN32
- if ((*target_activity_function) ())
- kill (PIDGET (inferior_ptid), SIGINT);
-#endif
- }
-}
-static int old_fcntl_flags;
+/* Create a new session if the inferior will run in a different tty.
+ A session is UNIX's way of grouping processes that share a controlling
+ terminal, so a new one is needed if the inferior terminal will be
+ different from GDB's.
-void
-set_sigio_trap (void)
+ Returns the session id of the new session, 0 if no session was created
+ or -1 if an error occurred. */
+pid_t
+create_tty_session (void)
{
- if (target_activity_function)
- {
- old_sigio = (void (*)()) signal (SIGIO, handle_sigio);
- fcntl (target_activity_fd, F_SETOWN, getpid ());
- old_fcntl_flags = fcntl (target_activity_fd, F_GETFL, 0);
- fcntl (target_activity_fd, F_SETFL, old_fcntl_flags | FASYNC);
- }
-}
+#ifdef HAVE_SETSID
+ pid_t ret;
-void
-clear_sigio_trap (void)
-{
- if (target_activity_function)
- {
- signal (SIGIO, old_sigio);
- fcntl (target_activity_fd, F_SETFL, old_fcntl_flags);
- }
-}
-#else /* No SIGIO. */
-void
-set_sigio_trap (void)
-{
- if (target_activity_function)
- internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
-}
+ if (!job_control || inferior_thisrun_terminal == 0)
+ return 0;
-void
-clear_sigio_trap (void)
-{
- if (target_activity_function)
- internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
+ ret = setsid ();
+ if (ret == -1)
+ warning ("Failed to create new terminal session: setsid: %s",
+ safe_strerror (errno));
+
+ return ret;
+#else
+ return 0;
+#endif /* HAVE_SETSID */
}
-#endif /* No SIGIO. */
-\f
/* This is here because this is where we figure out whether we (probably)
have job control. Just using job_control only does part of it because