X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Finflow.c;h=4cbcd5c74e691e8558c8088b2ad795c604006e51;hb=d66ff635bec25bf940cc6d173a92f7796f18b310;hp=71e06126878ef88e871956d6aeade9acff38efb3;hpb=6c95b8df7fef5273da71c34775918c554aae0ea8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/inflow.c b/gdb/inflow.c index 71e0612687..4cbcd5c74e 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -1,7 +1,5 @@ /* 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, 2008, - 2009 Free Software Foundation, Inc. + Copyright (C) 1986-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -27,13 +25,12 @@ #include "target.h" #include "gdbthread.h" #include "observer.h" - -#include "gdb_string.h" #include #include #include "gdb_select.h" #include "inflow.h" +#include "gdbcmd.h" #ifdef HAVE_SYS_IOCTL_H #include @@ -43,15 +40,11 @@ #define O_NOCTTY 0 #endif -#if defined (SIGIO) && defined (FASYNC) && defined (FD_SET) && defined (F_SETOWN) -static void handle_sigio (int); -#endif - extern void _initialize_inflow (void); static void pass_signal (int); -static void terminal_ours_1 (int); +static void child_terminal_ours_1 (int); /* Record terminal status separately for debugger and inferior. */ @@ -86,6 +79,10 @@ struct terminal_info unimportant. */ static struct terminal_info our_terminal_info; +/* Snapshot of our own tty state taken during initialization of GDB. + This is used as the initial tty state given to each new inferior. */ +static serial_ttystate initial_gdb_ttystate; + static struct terminal_info *get_inflow_inferior_data (struct inferior *); #ifdef PROCESS_GROUP_TYPE @@ -104,8 +101,8 @@ inferior_process_group (void) we save our handlers in these two variables and set SIGINT and SIGQUIT to SIG_IGN. */ -static void (*sigint_ours) (); -static void (*sigquit_ours) (); +static sighandler_t sigint_ours; +static sighandler_t sigquit_ours; /* The name of the tty (from the `tty' command) that we're giving to the inferior when starting it up. This is only (and should only @@ -125,6 +122,7 @@ static PROCESS_GROUP_TYPE gdb_getpgrp (void) { int process_group = -1; + #ifdef HAVE_TERMIOS process_group = tcgetpgrp (0); #endif @@ -138,12 +136,20 @@ gdb_getpgrp (void) } #endif -enum +enum gdb_has_a_terminal_flag_enum { yes, no, have_not_checked } gdb_has_a_terminal_flag = have_not_checked; +/* Set the initial tty state that is to be inherited by new inferiors. */ + +void +set_initial_gdb_ttystate (void) +{ + initial_gdb_ttystate = serial_get_tty_state (stdin_serial); +} + /* Does GDB have a terminal (on stdin)? */ int gdb_has_a_terminal (void) @@ -192,28 +198,28 @@ gdb_has_a_terminal (void) fprintf_unfiltered(gdb_stderr, "[%s failed in terminal_inferior: %s]\n", \ what, safe_strerror (errno)) -static void terminal_ours_1 (int); - /* Initialize the terminal settings we record for the inferior, before we actually run the inferior. */ void -terminal_init_inferior_with_pgrp (int pgrp) +child_terminal_init_with_pgrp (int pgrp) { - if (gdb_has_a_terminal ()) - { - struct inferior *inf = current_inferior (); - struct terminal_info *tinfo = get_inflow_inferior_data (inf); - - /* We could just as well copy our_ttystate (if we felt like - adding a new function serial_copy_tty_state()). */ - xfree (tinfo->ttystate); - tinfo->ttystate = serial_get_tty_state (stdin_serial); + struct inferior *inf = current_inferior (); + struct terminal_info *tinfo = get_inflow_inferior_data (inf); #ifdef PROCESS_GROUP_TYPE - tinfo->process_group = pgrp; + /* Store the process group even without a terminal as it is used not + only to reset the tty foreground process group, but also to + interrupt the inferior. */ + tinfo->process_group = pgrp; #endif + if (gdb_has_a_terminal ()) + { + xfree (tinfo->ttystate); + tinfo->ttystate = serial_copy_tty_state (stdin_serial, + initial_gdb_ttystate); + /* Make sure that next time we call terminal_inferior (which will be before the program runs, as it needs to be), we install the new process group. */ @@ -226,36 +232,38 @@ terminal_init_inferior_with_pgrp (int pgrp) and gdb must be able to restore it correctly. */ void -terminal_save_ours (void) +gdb_save_tty_state (void) { if (gdb_has_a_terminal ()) { - /* We could just as well copy our_ttystate (if we felt like adding - a new function serial_copy_tty_state). */ xfree (our_terminal_info.ttystate); our_terminal_info.ttystate = serial_get_tty_state (stdin_serial); } } void -terminal_init_inferior (void) +child_terminal_init (struct target_ops *self) { #ifdef PROCESS_GROUP_TYPE - /* This is for Lynx, and should be cleaned up by having Lynx be a separate - debugging target with a version of target_terminal_init_inferior which - passes in the process group to a generic routine which does all the work - (and the non-threaded child_terminal_init_inferior can just pass in - inferior_ptid to the same routine). */ + /* This is for Lynx, and should be cleaned up by having Lynx be a + separate debugging target with a version of target_terminal_init + which passes in the process group to a generic routine which does + all the work (and the non-threaded child_terminal_init can just + pass in inferior_ptid to the same routine). */ /* We assume INFERIOR_PID is also the child's process group. */ - terminal_init_inferior_with_pgrp (PIDGET (inferior_ptid)); + child_terminal_init_with_pgrp (ptid_get_pid (inferior_ptid)); #endif /* PROCESS_GROUP_TYPE */ } /* Put the inferior's terminal settings into effect. - This is preparation for starting or resuming the inferior. */ + This is preparation for starting or resuming the inferior. + + N.B. Targets that want to use this with async support must build that + support on top of this (e.g., the caller still needs to remove stdin + from the event loop). E.g., see linux_nat_terminal_inferior. */ void -terminal_inferior (void) +child_terminal_inferior (struct target_ops *self) { struct inferior *inf; struct terminal_info *tinfo; @@ -290,9 +298,9 @@ terminal_inferior (void) if (!job_control) { - sigint_ours = (void (*)()) signal (SIGINT, SIG_IGN); + sigint_ours = signal (SIGINT, SIG_IGN); #ifdef SIGQUIT - sigquit_ours = (void (*)()) signal (SIGQUIT, SIG_IGN); + sigquit_ours = signal (SIGQUIT, SIG_IGN); #endif } @@ -333,22 +341,29 @@ terminal_inferior (void) so that no input is discarded. After doing this, either terminal_ours or terminal_inferior - should be called to get back to a normal state of affairs. */ + should be called to get back to a normal state of affairs. + + N.B. The implementation is (currently) no different than + child_terminal_ours. See child_terminal_ours_1. */ void -terminal_ours_for_output (void) +child_terminal_ours_for_output (struct target_ops *self) { - terminal_ours_1 (1); + child_terminal_ours_1 (1); } /* Put our terminal settings into effect. First record the inferior's terminal settings - so they can be restored properly later. */ + so they can be restored properly later. + + N.B. Targets that want to use this with async support must build that + support on top of this (e.g., the caller still needs to add stdin to the + event loop). E.g., see linux_nat_terminal_ours. */ void -terminal_ours (void) +child_terminal_ours (struct target_ops *self) { - terminal_ours_1 (0); + child_terminal_ours_1 (0); } /* output_only is not used, and should not be used unless we introduce @@ -356,7 +371,7 @@ terminal_ours (void) flags. */ static void -terminal_ours_1 (int output_only) +child_terminal_ours_1 (int output_only) { struct inferior *inf; struct terminal_info *tinfo; @@ -376,18 +391,18 @@ terminal_ours_1 (int output_only) if (tinfo->run_terminal != NULL || gdb_has_a_terminal () == 0) return; - + else { #ifdef SIGTTOU /* Ignore this signal since it will happen when we try to set the pgrp. */ - void (*osigttou) () = NULL; + sighandler_t osigttou = NULL; #endif int result; #ifdef SIGTTOU if (job_control) - osigttou = (void (*)()) signal (SIGTTOU, SIG_IGN); + osigttou = signal (SIGTTOU, SIG_IGN); #endif xfree (tinfo->ttystate); @@ -412,8 +427,8 @@ terminal_ours_1 (int output_only) mode, to avoid flushing input. We need to do the same thing regardless of output_only, because we don't have separate terminal_is_ours and terminal_is_ours_for_output flags. It's OK, - though, since readline will deal with raw mode when/if it needs to. - */ + though, since readline will deal with raw mode when/if it needs + to. */ serial_noflush_set_tty_state (stdin_serial, our_terminal_info.ttystate, tinfo->ttystate); @@ -428,7 +443,8 @@ terminal_ours_1 (int output_only) used to check for an error here, so perhaps there are other such situations as well. */ if (result == -1) - fprintf_unfiltered (gdb_stderr, "[tcsetpgrp failed in terminal_ours: %s]\n", + fprintf_unfiltered (gdb_stderr, + "[tcsetpgrp failed in child_terminal_ours: %s]\n", safe_strerror (errno)); #endif #endif /* termios */ @@ -469,14 +485,11 @@ static const struct inferior_data *inflow_inferior_data; static void inflow_inferior_data_cleanup (struct inferior *inf, void *arg) { - struct terminal_info *info; + struct terminal_info *info = (struct terminal_info *) arg; - info = inferior_data (inf, inflow_inferior_data); - if (info != NULL) - { - xfree (info->run_terminal); - xfree (info); - } + xfree (info->run_terminal); + xfree (info->ttystate); + xfree (info); } /* Get the current svr4 data. If none is found yet, add it now. This @@ -487,10 +500,10 @@ get_inflow_inferior_data (struct inferior *inf) { struct terminal_info *info; - info = inferior_data (inf, inflow_inferior_data); + info = (struct terminal_info *) inferior_data (inf, inflow_inferior_data); if (info == NULL) { - info = XZALLOC (struct terminal_info); + info = XCNEW (struct terminal_info); set_inferior_data (inf, inflow_inferior_data, info); } @@ -504,15 +517,15 @@ get_inflow_inferior_data (struct inferior *inf) list. */ static void -inflow_inferior_exit (int pid) +inflow_inferior_exit (struct inferior *inf) { - struct inferior *inf = find_inferior_pid (pid); struct terminal_info *info; - info = inferior_data (inf, inflow_inferior_data); + info = (struct terminal_info *) inferior_data (inf, inflow_inferior_data); if (info != NULL) { xfree (info->run_terminal); + xfree (info->ttystate); xfree (info); set_inferior_data (inf, inflow_inferior_data, NULL); } @@ -525,10 +538,19 @@ copy_terminal_info (struct inferior *to, struct inferior *from) tinfo_to = get_inflow_inferior_data (to); tinfo_from = get_inflow_inferior_data (from); + + xfree (tinfo_to->run_terminal); + xfree (tinfo_to->ttystate); + *tinfo_to = *tinfo_from; + if (tinfo_from->run_terminal) tinfo_to->run_terminal = xstrdup (tinfo_from->run_terminal); + + if (tinfo_from->ttystate) + tinfo_to->ttystate + = serial_copy_tty_state (stdin_serial, tinfo_from->ttystate); } void @@ -538,7 +560,7 @@ term_info (char *arg, int from_tty) } void -child_terminal_info (char *args, int from_tty) +child_terminal_info (struct target_ops *self, const char *args, int from_tty) { struct inferior *inf; struct terminal_info *tinfo; @@ -555,7 +577,8 @@ child_terminal_info (char *args, int from_tty) inf = current_inferior (); tinfo = get_inflow_inferior_data (inf); - printf_filtered (_("Inferior's terminal status (currently saved by GDB):\n")); + printf_filtered (_("Inferior's terminal status " + "(currently saved by GDB):\n")); /* First the fcntl flags. */ { @@ -568,7 +591,7 @@ child_terminal_info (char *args, int from_tty) #ifndef O_ACCMODE #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) #endif - /* (O_ACCMODE) parens are to avoid Ultrix header file bug */ + /* (O_ACCMODE) parens are to avoid Ultrix header file bug. */ switch (flags & (O_ACCMODE)) { case O_RDONLY: @@ -637,7 +660,7 @@ new_tty_prefork (const char *ttyname) inferior_thisrun_terminal = ttyname; } - +#if !defined(__GO32__) && !defined(_WIN32) /* 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. */ @@ -650,6 +673,7 @@ check_syscall (const char *msg, int result) _exit (1); } } +#endif void new_tty (void) @@ -662,13 +686,13 @@ new_tty (void) #ifdef TIOCNOTTY /* Disconnect the child process from our controlling terminal. On some systems (SVR4 for example), this may cause a SIGTTOU, so temporarily - ignore SIGTTOU. */ + ignore SIGTTOU. */ tty = open ("/dev/tty", O_RDWR); if (tty > 0) { - void (*osigttou) (); + sighandler_t osigttou; - osigttou = (void (*)()) signal (SIGTTOU, SIG_IGN); + osigttou = signal (SIGTTOU, SIG_IGN); ioctl (tty, TIOCNOTTY, 0); close (tty); signal (SIGTTOU, osigttou); @@ -701,7 +725,7 @@ new_tty (void) 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", + warning (_("GDB: Failed to set controlling terminal: %s"), safe_strerror (errno)); #endif @@ -733,17 +757,17 @@ new_tty_postfork (void) /* Call set_sigint_trap when you need to pass a signal on to an attached - process when handling SIGINT */ + process when handling SIGINT. */ static void pass_signal (int signo) { #ifndef _WIN32 - kill (PIDGET (inferior_ptid), SIGINT); + kill (ptid_get_pid (inferior_ptid), SIGINT); #endif } -static void (*osig) (); +static sighandler_t osig; static int osig_set; void @@ -754,7 +778,7 @@ set_sigint_trap (void) if (inf->attach_flag || tinfo->run_terminal) { - osig = (void (*)()) signal (SIGINT, pass_signal); + osig = signal (SIGINT, pass_signal); osig_set = 1; } else @@ -790,7 +814,7 @@ create_tty_session (void) ret = setsid (); if (ret == -1) - warning ("Failed to create new terminal session: setsid: %s", + warning (_("Failed to create new terminal session: setsid: %s"), safe_strerror (errno)); return ret; @@ -868,7 +892,7 @@ _initialize_inflow (void) #ifdef _SC_JOB_CONTROL job_control = sysconf (_SC_JOB_CONTROL); #else - job_control = 0; /* have to assume the worst */ + job_control = 0; /* Have to assume the worst. */ #endif /* _SC_JOB_CONTROL */ #endif /* _POSIX_JOB_CONTROL */ #endif /* HAVE_TERMIOS */ @@ -884,5 +908,5 @@ _initialize_inflow (void) observer_attach_inferior_exit (inflow_inferior_exit); inflow_inferior_data - = register_inferior_data_with_cleanup (inflow_inferior_data_cleanup); + = register_inferior_data_with_cleanup (NULL, inflow_inferior_data_cleanup); }