1

I start emacs from my init script upon login. Every now and then I accidentally suspend it with ctrl+z, and I don't know how to recover from that.

Had I started from the terminal, jobs and fg would do the trick, but in that case there is no terminal to run from.

I can see the process running:

gauthier@sobel:~/data $ ps aux | grep emacs
gauthier  2932  0.0  0.6 565500 112540 ?       Sl   Apr14   0:11 emacs
gauthier 15189  0.0  0.0  11744   932 pts/2    S+   15:54   0:00 grep --color=auto emacs
8
  • Doesn't jobs show emacs ?
    – heemayl
    Apr 15, 2015 at 13:57
  • Oh, actually. Clicking on the emacs frame worked. I have focus on mouse hover, but somehow only hovering did not work. I'm not used to clicking to give focus, and changing focus with the keyboard did not help either. Anyway, I'm still interested in knowing how to unsuspend the process from the terminal, as an academic exercise.
    – Gauthier
    Apr 15, 2015 at 13:58
  • @heemayl: jobs shows only the processes started from the terminal in which you type it.
    – Gauthier
    Apr 15, 2015 at 13:59
  • Hmm..did not read it carefully..
    – heemayl
    Apr 15, 2015 at 14:10
  • Sorry I was wrong. Just clicking on the window does not help, it has somehow to be redrawn by the window manager.
    – Gauthier
    Apr 15, 2015 at 15:01

2 Answers 2

2

You can run

kill -SIGCONT [pid]

or

killall -SIGCONT [process name]

to resume the process[es] with the specified PID or process name.

2
  • I was really hoping this would work, but it does not. Emacs is still asleep. I tried running that with sudo, but nope.
    – Gauthier
    Apr 15, 2015 at 14:59
  • See my new comment, apparently a redraw from the WM is needed to wake up.
    – Gauthier
    Apr 15, 2015 at 15:01
1

Emacs wasn't really suspended.

As we discovered through troubleshooting, emacs was not really suspended. Suspended processes show T as part of their state when viewed via ps, whereas in your situation emacs showed S, which simply means it was waiting on an event (in this case, waiting on user interaction).

As explained in the "PROCESS STATE CODES" section of man ps:

               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is
                    being traced

When a process is suspended, that is considered a job control signal, since suspending processes is primarily done as part of job control (with & at the end of a command, Ctrl+Z issued in the terminal, and the jobs shell builtin). See the ps manpage itself for documentation of the other state codes, D, R, W, X, and Z.

Emacs was iconified, not suspended. When Ctrl+Z is issued to a foreground process in a terminal, it causes the process to be suspended. But you pressed Ctrl+Z while in a GUI emacs window. Ctrl+Z doesn't suspend programs when given this way--for example, in many applications (such as Firefox and LibreOffice) Ctrl+Z is the keystroke for undo.

As you were able to confirm, when using emacs through a graphical interface Ctrl+Z is key combination to iconify (i.e., minimize) the window or to deiconify (i.e., restore) it if it is already iconified. Of course, you must have the iconified window selected to deiconify it with Ctrl+Z, which it appears your window manager may not support.

Note that, when you press Ctrl+Z while in a terminal window, it is not likely that emacs is itself intercepting it and suspending itself. Rather, Ctrl+Z issued in a terminal generally suspends processed, and Ctrl+Z issued in a GUI window generally does not.

Since you said you're "still interested in knowing how to unsuspend the process from the terminal" and an explanation of how to know if one's process is really suspended (and when Ctrl+Z does and does not suspend a process) makes for a reasonable introduction to an answer about that, I have decided to devote the remainder of this answer to addressing that part of the question.

Resuming Suspended Processes from a Different Terminal

If you have access to a suspended program's controlling terminal, the jobs, fg, and bg builtins allow you to view and resume it. If you don't have access to the program's controlling terminal and all you need to do is resume the process but not give it input, or read its output, on a terminal, you can send the process SIGCONT as detailed in zhongfu's answer. This is probably what you would do if a graphical program had been suspended and you couldn't resume it from its controlling terminal. This is because the primary way we interact with most GUI apps most of the time is through their graphical UIs, and not through the terminal.

However, if you need to detach a process's standard streams from its original terminal and reattach them to a different terminal--that is, to resume a suspended process and interact with it in a different terminal from the one it was started in--that is not so simple.

  • You would mainly need this if it were a command-line program designed to interact with the user primarily through a terminal rather than through some other mechanism like a GUI or a local web server. For example, you're much more likely to need to do this for emacs -nw than for GUI emacs.

Reattaching a Process to a Different Terminal, If You Planned Ahead

If you anticipate this need when you run the program, you can avoid it altogether by starting the process in a terminal multiplexer rather than an ordinary terminal. screen and tmux do this; see man screen and man tmux for details. (See also byobu.) A process started in a terminal multiplexer not connected directly to the terminal through which you interact with it, but instead to a pseduo terminal provided by the multiplexer.

  • For example, you could run screen emacs in one terminal, then later detach it from that terminal by pressing Ctrl+A followed by Ctrl+D and open it on another terminal (or the same one) by running screen -r. Or, if you never detached it form the first terminal, you detach it from there and reattach it to the current terminal with screen -rd.

Reattaching a Process to a Different Terminal, If You Didn't Plan Ahead

If you didn't start your program in a terminal multiplexer and need to detach it from its original and attach it to a new one, this is usually possible, though nontrivial with the utilities installed in Ubuntu by default. It can be done by opening and manipulating the process in a debugger.

Fortunately, utilities have been written with which this may be done easily--or at least attempted easily. I suggest reptyr. (See also injcode, neercs, and the comparison of the three on the reptyr page.) Reptyr's readme file on the reptyr github page gives usage information. On Ubuntu, to download and build reptyr, run its testsuite, and install it, you can use these commands:

# Install build dependencies and set up /usr/local/src for administrators.
sudo apt-get update && sudo apt-get install build-essential git python-pip
pip install pexpect
cd /usr/local/src && sudo chgrp sudo . && sudo chmod g+w,+t .

# Retrieve, configure, build, test, and install reptyr.
git clone https://github.com/nelhage/reptyr.git && cd reptyr
make && sudo make test install

You may notice that I make the test target as root with sudo. Usual best practice is to build and test software as a normal user and elevate to root just to install it. However, in Ubuntu's default configuration, reptyr does not work when run by a non-root user. This is because reptyr manipulates a process's file descriptors by attaching to the process as a debugger, but as a security feature non-root processes are prohibited from debugging processes that are not their descendants.

When you actually use the reptyr command, you won't run it with sudo. Instead you'll want to run reptyr as the same user who owns the process, from a terminal belonging to that user. (There might be a way to get it to work without doing that, but it's only worked for me that way.)

Using reptyr on Ubuntu

Allowing processes to debug non-descendants owned by the same user is likely to cause problems only if a running program is being successfully exploited (or if you have malware). One way to allow reptyr to work while keeping your security risk relatively low is to allow it only when you need to run reptyr--which is probably, hopefully, a rare occurrence--and re-disable it afterwards.

So, suppose you've started a non-graphical Emacs instance (in an inaccessible terminal):

emacs -nw

This may or may not be suspended. From another terminal, change ptrace_scope from 1 to 0 to allow processes to debug processes that are not their descendants:

echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

Then run reptyr, passing the process's PID as an argument, to attempt to detach it from the old terminal and attach it to the new one:

reptyr PID

You can find the PID in the output of ps x or with pgrep or pidof. If there's only one emacs running, you can find the PID and pass it to reptyr in a single command:

reptyr $(pidof emacs)

I've found that this usually works but sometimes doesn't. If reptyr shows no output at all, you may have to press Ctrl+Z to use the program. (I don't know why that is, but running ps reveals nothing is suspended or unsuspended when I press Ctrl+Z in this specific situation, so I suspect it has to do with the interaction between reptyr and my shell's job control facilities.)

Job control may not be fully functional with the reattached process; for example, you may not always be able to suspend it with Ctrl+Z.

After you're done with reptyr you can set ptrace_scope back to 1 for security:

echo 1 | sudo tee /proc/sys/kernel/yama/ptrace_scope

It is easier and more reliable to plan ahead when possible. If the terminal you start an interactive program on might become inaccessible, it's best to use a terminal multiplexer like screen or tmux (as detailed above).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .