Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: cannot set terminal process group (-1): Inappropriate ioctl for device #51

Closed
alhafoudh opened this issue Jan 8, 2016 · 15 comments · Fixed by #122
Closed

Error: cannot set terminal process group (-1): Inappropriate ioctl for device #51

alhafoudh opened this issue Jan 8, 2016 · 15 comments · Fixed by #122

Comments

@alhafoudh
Copy link

When I have dumb-init in ENTRYPOINT like this

...
ENTRYPOINT ["/usr/bin/dumb-init"]
...

and then try to run bash with tty and interactively, I get this error:

docker run --rm -t -i dumb_init_image bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
...
@chriskuehl
Copy link
Contributor

@alhafoudh thanks for the issue! I was able to reproduce it, we'll look into it.

Just to confirm, are you still getting a usable shell? (I'm getting the error printed, but still get a shell afterwards. Just want to confirm the behavior is the same for you.)

@alhafoudh
Copy link
Author

Yes, I have usage shell after the error

bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root@e60f020604eb:/#

@chriskuehl
Copy link
Contributor

@alhafoudh still looking into the root cause. I think it's something we can fix.

For now a workaround is to run in non-setsid mode using -c, e.g.

ENTRYPOINT ["/usr/bin/dumb-init", "-c", "--"]

The only difference behavior-wise is that signals are only forwarded to your direct child. So if you have a process tree like

PID 1: dumb-init
+---- PID 2: python server
    +---- PID 3: worker process
    +---- PID 4: worker process
    +---- PID 5: worker process

when you send docker signal, the signal is only delivered to PID 2 and not everything in the process group (potentially including the workers).

This is usually acceptable behavior since the server is supposed to handle signaling its workers before it dies anyway. Unfortunately there are some exceptions, which is why the default is setsid mode.

I'll keep looking into this and get back to you.

michaelsauter added a commit to michaelsauter/docker-alpine that referenced this issue Jan 12, 2016
See http://engineeringblog.yelp.com/2016/01/dumb-init-an-init-for-docker.html.

Also configure it to proxy only to direct children, which seems appropriate
and also works around Yelp/dumb-init#51.
@pclalv
Copy link

pclalv commented Feb 22, 2016

@chriskuehl with ENTRYPOINT ["/usr/bin/dumb-init", "-c", "--"] in my Dockerfile, i get "[dumb-init] -c: No such file or directory". interestingly, i only get that error when the container is running on mesos; docker runing it works fine

@chriskuehl
Copy link
Contributor

@pclalv can you provide some information on how you're running it on Mesos? What frameworks are you using (e.g. Marathon/Chronos) and how are you passing the command/arguments to the framework?

I've been working with Mesos a lot recently and have found the argument passing to be a bit tricky with Docker. For example, Chronos seems to combine arguments and command into a space-delimited string which becomes the first argument after the ENTRYPOINT, and then the strings in the arguments list are still appended to the end of the arguments, which doesn't make much sense (there's a bug for that: mesos/chronos#567).

Any details you can provide would be really helpful to reproducing it.

@pclalv
Copy link

pclalv commented Feb 23, 2016

of course, @chriskuehl. i'm using Mesos 0.26.0 and Marathon 0.15.2, and passing arguments to the framework with the args parameter.

@asottile
Copy link
Contributor

May be related to #78

@ghost
Copy link

ghost commented Jun 22, 2016

The setsid() system call to create a new process group detaches the spawned process from a controlling tty. Therefore programs like bash complain, that they can't use job control. Re-attaching the controlling tty won't work, because the tty is still in use as a controlling tty for dumb-init.

So my suggestion is to remove the controlling tty from dumb-init and attach it to the spawned process (when in setsid mode).

Here my patch:

diff --git a/dumb-init.c b/dumb-init.c
index 624dd1f..424a8db 100644
--- a/dumb-init.c
+++ b/dumb-init.c
@@ -15,6 +15,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -236,6 +237,15 @@ char **parse_command(int argc, char *argv[]) {
 int main(int argc, char *argv[]) {
     char **cmd = parse_command(argc, argv);

+    /* detach dumb-init from controlling tty */
+    if (use_setsid && ioctl(0, TIOCNOTTY, NULL) == -1) {
+        DEBUG(
+            "Unable to detach from controlling tty (errno=%d %s).\n",
+            errno,
+            strerror(errno)
+        );
+    }
+
     child_pid = fork();
     if (child_pid < 0) {
         PRINTERR("Unable to fork. Exiting.\n");
@@ -251,6 +261,13 @@ int main(int argc, char *argv[]) {
                 );
                 exit(1);
             }
+            if (ioctl(0, TIOCSCTTY, NULL) == -1) {
+                DEBUG(
+                    "Unable to attach to controlling tty (errno=%d %s).\n",
+                    errno,
+                    strerror(errno)
+                );
+            }
             DEBUG("setsid complete.\n");
         }
         execvp(cmd[0], &cmd[0]);

This patch uses this controlling tty stuff only in setsid mode. Maybe it's also interesting in the single-child mode. It may ease the handling of SIGTSTP/SIGTTIN/SIGTTOU, as dumb-init has no longer the controlling tty and therefore should not receive those signals.

@athakwani
Copy link

any update on this? I am seeing the same warning.

@chriskuehl
Copy link
Contributor

@athakwani, @Ehlers, thanks a lot for both the patch and the bump!

I just tried the patch out locally and it seems to be working great (all the existing tests pass, and we do test the behavior we care about pretty extensively).

I was a little concerned about what effect it would have on the new --rewrite flag that was added, but it appears to work with no additional changes.

I'll spend a little more time looking into what exactly this is doing, but I'll plan to write a test for this new behavior and make a PR shortly.

@samrocketman
Copy link

samrocketman commented Oct 8, 2016

@Ehlers perhaps open a PR for hacktoberfest? :)

@chriskuehl
Copy link
Contributor

PRs definitely welcome! :)

I spent a bit of time trying to write a regression test for this bug, but wasn't quite able to get something reliable yet. I'll give it another attempt on Monday if nothing else.

@chriskuehl
Copy link
Contributor

Patch is included in v1.2.0 (just released), thanks all!

@samrocketman
Copy link

Yay thanks! 😁

@javabean
Copy link

Unfortunately I still see this error message, using dumb-init 1.2.0 (Ubuntu 16.04, both directly in the host shell, and inside a docker run --rm -ti ubuntu:16.04 bash):

$ ./dumb-init_1.2.0_amd64 bash
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
$ exit
$ ./dumb-init_1.2.0_amd64 -c bash
$ exit

Note that tini does not exhibit this problem (i.e. works fine with and without its -g flag).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants