+ if (async_exec)
+ {
+ /* The user requested an `attach&', so be sure to leave threads
+ that didn't get a signal running. */
+
+ /* Immediatelly resume all suspended threads of this inferior,
+ and this inferior only. This should have no effect on
+ already running threads. If a thread has been stopped with a
+ signal, leave it be. */
+ if (non_stop)
+ proceed_after_attach (inferior->pid);
+ else
+ {
+ if (inferior_thread ()->stop_signal == TARGET_SIGNAL_0)
+ {
+ clear_proceed_status ();
+ proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0);
+ }
+ }
+ }
+ else
+ {
+ /* The user requested a plain `attach', so be sure to leave
+ the inferior stopped. */
+
+ if (target_can_async_p ())
+ async_enable_stdin ();
+
+ /* At least the current thread is already stopped. */
+
+ /* In all-stop, by definition, all threads have to be already
+ stopped at this point. In non-stop, however, although the
+ selected thread is stopped, others may still be executing.
+ Be sure to explicitly stop all threads of the process. This
+ should have no effect on already stopped threads. */
+ if (non_stop)
+ target_stop (pid_to_ptid (inferior->pid));
+
+ /* Tell the user/frontend where we're stopped. */
+ normal_stop ();
+ if (deprecated_attach_hook)
+ deprecated_attach_hook ();
+ }
+}
+
+struct attach_command_continuation_args
+{
+ char *args;
+ int from_tty;
+ int async_exec;
+};
+
+static void
+attach_command_continuation (void *args)
+{
+ struct attach_command_continuation_args *a = args;
+ attach_command_post_wait (a->args, a->from_tty, a->async_exec);
+}
+
+static void
+attach_command_continuation_free_args (void *args)
+{
+ struct attach_command_continuation_args *a = args;
+ xfree (a->args);
+ xfree (a);
+}
+
+void
+attach_command (char *args, int from_tty)
+{
+ char *exec_file;
+ char *full_exec_path = NULL;
+ int async_exec = 0;
+
+ dont_repeat (); /* Not for the faint of heart */
+
+ if (target_supports_multi_process ())
+ /* Don't complain if we can be attached to multiple processes. */
+ ;
+ else if (target_has_execution)
+ {
+ if (query ("A program is being debugged already. Kill it? "))
+ target_kill ();
+ else
+ error (_("Not killed."));
+ }
+
+ /* Clean up any leftovers from other runs. Some other things from
+ this function should probably be moved into target_pre_inferior. */
+ target_pre_inferior (from_tty);
+
+ if (non_stop && !target_supports_non_stop ())
+ error (_("Cannot attach to this target in non-stop mode"));
+
+ if (args)
+ {
+ async_exec = strip_bg_char (&args);
+
+ /* If we get a request for running in the bg but the target
+ doesn't support it, error out. */
+ if (async_exec && !target_can_async_p ())
+ error (_("Asynchronous execution not supported on this target."));
+ }
+
+ /* If we don't get a request of running in the bg, then we need
+ to simulate synchronous (fg) execution. */
+ if (!async_exec && target_can_async_p ())
+ {
+ /* Simulate synchronous execution */
+ async_disable_stdin ();
+ }
+
+ target_attach (args, from_tty);
+
+ /* Set up the "saved terminal modes" of the inferior
+ based on what modes we are starting it with. */
+ target_terminal_init ();
+
+ /* Set up execution context to know that we should return from
+ wait_for_inferior as soon as the target reports a stop. */
+ init_wait_for_inferior ();
+ clear_proceed_status ();
+
+ if (non_stop)
+ {
+ /* If we find that the current thread isn't stopped, explicitly
+ do so now, because we're going to install breakpoints and
+ poke at memory. */
+
+ if (async_exec)
+ /* The user requested an `attach&'; stop just one thread. */
+ target_stop (inferior_ptid);
+ else
+ /* The user requested an `attach', so stop all threads of this
+ inferior. */
+ target_stop (pid_to_ptid (ptid_get_pid (inferior_ptid)));
+ }
+
+ /* Some system don't generate traps when attaching to inferior.
+ E.g. Mach 3 or GNU hurd. */
+ if (!target_attach_no_wait)
+ {
+ struct inferior *inferior = current_inferior ();
+
+ /* Careful here. See comments in inferior.h. Basically some
+ OSes don't ignore SIGSTOPs on continue requests anymore. We
+ need a way for handle_inferior_event to reset the stop_signal
+ variable after an attach, and this is what
+ STOP_QUIETLY_NO_SIGSTOP is for. */
+ inferior->stop_soon = STOP_QUIETLY_NO_SIGSTOP;
+
+ if (target_can_async_p ())
+ {
+ /* sync_execution mode. Wait for stop. */
+ struct attach_command_continuation_args *a;
+
+ a = xmalloc (sizeof (*a));
+ a->args = xstrdup (args);
+ a->from_tty = from_tty;
+ a->async_exec = async_exec;
+ add_continuation (inferior_thread (),
+ attach_command_continuation, a,
+ attach_command_continuation_free_args);
+ return;
+ }