Open Bug 147274 Opened 22 years ago Updated 2 years ago

freeze when helper app reads from stdin (e.g. ghostscript)

Categories

(Firefox :: File Handling, defect)

x86
Linux
defect

Tracking

()

People

(Reporter: gwalla, Unassigned)

References

Details

(Keywords: hang)

Attachments

(2 files, 1 obsolete file)

When attempting to read a PostScript file from the web using Ghostscript,
Mozilla (RC2) froze and the process had to be killed. Closing the ghostscript
window does not bring Mozilla back. After killing the wayward Mozilla, starting
a new instance of Mozilla works fine.

To reproduce:
1) click on a link to a PostScript file
2) in the "Open with application or save" dialog, select "Open with" and choose
the ghostscript application (/usr/bin/ghostscript in my system)
3) a ghostscript window will pop up, but Mozilla's windows will cease to repaint
until the process is killed

I can reproduce this consistently.
Does this only happen with GhostScript or any PS viewer?  Does gv work OK?

Do you see this both trunk and branch or trunk-only?
and.. what is the ghostscript version?
Can reproduce - current trunk CVS, Linux

Download manager for some reason first list the file as downloaded - and then
lists it once more - as not started. By that time gs has already spawned and is
displaying the .ps file, and repaint stops

No CPU usage. killall mozilla-bin doesn't help, had to kill -9 on the first PID
in thread, but after this and quitting gs, one remaining mozilla-bin process
can't be killed but has to be terminated by exiting the xterm it was started
from ("There are stopped jobs")

Repeated twice, two different versions of ghostscript, latest being
ghostscript-6.52-8 from RH7.3. Fonts are installed OK.
rkaa, is this just a ghostcript problem or also a problem with other viewers?  
Is this a regression?  Could you possibly hunt down when this behavior started 
if so?
I wonder if this is an old one, really. No problem if i for instance choose
kghostview instead. Ghostscript, on the other hand is interactive. When mozilla
is started from console and i try to open via moz in gs, i see gs throw a
command-prompt in console, with an "enter to continue".

Viewing the same file direct with gs, i can then "page" with the enter key, and
get a "finished" prompt from where i can "quit".

Via Mozilla, the first "continue" prompt appears, but when i hit enter there, i
see "Stopped [mozilla]" or thereabouts. No further "paging" possible and Moz is
frozen.

After i close gs with the X button, that process is still hanging as well.

Haven't checked further but this reminds me of bug 62993 and bug 145054
Oh.  So the problem is that the app in question tries to read from stdin and
stops.... the question is why this stops Mozilla.

Could you set the helper to something like "cat" to test whether this is just
true in general for any helper app that tries to read from the console?  Also,
if you foreground the Mozilla process in your terminal, is paging possible?
well.. for fun i tried to open the file with /bin/more. That too causes a full
hang and similar ghosted processes, but different from with gs, the
downloadmanger didn't start.
OK.  I'll take this and check it out; it sounds like any app that blocks on a 
tty read will hang us -- not good.  ;)
Assignee: law → bzbarsky
Keywords: hang
Priority: -- → P1
Target Milestone: --- → mozilla1.1beta
This actually sound like mozilla is running in the background and 
background processes are not allowed to read or write from the terminal.

From the bash docs:

       "To facilitate the implementation of the user interface to
       job control, the operating system maintains the notion of
       a current terminal process group ID.  Members of this pro-
       cess group (processes whose process group ID is equal to
       the current terminal process group ID) receive keyboard-
       generated signals such as SIGINT.  These processes are
       said to be in the foreground.  Background processes are
       those whose process group ID differs from the terminal's;
       such processes are immune to keyboard-generated signals.
       Only foreground processes are allowed to read from or
       write to the terminal.  Background processes which attempt
       to read from (write to) the terminal are sent a SIGTTIN
       (SIGTTOU) signal by the terminal driver, which, unless
       caught, suspends the process."

I have no problem if I run mozilla in the foreground. I don't think 
there's a real bug here.
The bug is that a _helper_ opening the tty hangs Mozilla.  The helper should be 
getting SIGTTIN and suspending.  It sounds like Mozilla is getting the signal 
as well or something silly like that....
It does look like a problem with running Mozilla as a background process.
Running it as "/usr/local/mozilla/mozilla" works fine...ghostscript gets the TTY
and pressing enter to turn pages works. Running it as
"/usr/local/mozilla/mozilla &" (a background process) causes the problem.

However, I still think this is a problem. I run Mozilla from the WindowMaker
applications menu, which launches everything in the background (since there is
no corresponding TTY). And I shouldn't have to have a useless xterm floating
about just so that when I encounter a PostScript file I can read it.
May i ask why you don't use ghostview? I never used ghostscript itself like this
before, but it seems it by default lay out multipage documents utterly
unreadable (all pages displays->text too small to read)
I don't have ghostview...I'll go get a copy. Still, that doesn't really solve
the core issue, which is that Mozilla comes to a screeching halt if you "open
with..." any application that uses a TTY when running Mozilla as a background
process.
> It sounds like Mozilla is getting the signal as well or something
> silly like that....

Quite right. Mozilla and all its child processes share the same tty so they're
in the same process group. The kernel can't know which of these processes are
actually interested in tty activity so it sends a signal to all of them. The
default handler just stops the process. You have to actively express
disinterest.

This isn't just a mozilla problem. I see it occasionally when I do
 "./configure &" and one of the little test programs talks to the tty.

I suggest just adding a relnote. "Fixing" this is hard.

BTW, most distributions already have "gv" which works quite well.
> The kernel can't know which of these processes are actually interested in tty
> activity 

Um?  What about just looking at the PID of the process making the open() call? 
I'm having a hard time believing that the whole setup is as braindead as 
that....

Even if fixing this is hard, we still want to try and fix it, imo.

A workaround for this is to mark ghostscript as "needsterminal" (and wait for 
that to work).
> Um?  What about just looking at the PID of the process making the open() 
> call?

stdin is already open .


> I'm having a hard time believing that the whole setup is as braindead 
> as that....

I'm not. See the glibc docs on job control for some of the flavor of the 
problem.

> Even if fixing this is hard, we still want to try and fix it, imo.

The problem is figuring out what the correct "fix" is.


> A workaround for this is to mark ghostscript as "needsterminal" (and 
> wait for that to work).

Which won't do much for the next program with the same problem. You 
still need a relnote.
I agree that a relnote is good.  That should be taken to the 1.0 relnote bug.

Tenthumbs, will the "close on exec" bug you filed recently affect this problem 
in any way?

Is there any reason Mozilla itself should be reading from stdin?  If not, 
possible things to try would be:

1)  Close stdin at startup (this makes it impossible to pass the stdin file
    descriptor to child processes, unfortunately)
2)  Having the startup script start Mozilla with stding redirected
    from /dev/null or something.  This may lead to odd behavior by gs (as it
    attempts to read /dev/null and possibly gets an infinite stream of 0s).
3)  Just catching the signal in question and ignoring it (this could be done by
    the appshell so that embedding clients are not affected).
Despite the fact that I make a lot of fun of unix, most of the rules are
there for a reason. If a background process could read from the terminal
then it could silently capture keystrokes like, say, a password. A Bad
Thing so it's not allowed.

The close-on exec thing (bug 147659) is about closing everything except
stdin, stdout, and stderr.

Mozilla shouldn't mess with stdin, etc. I can easily imagine a helper
app that would want to talk to the terminal. Maybe it wants a password
before continuing, maybe something else.

As for the possibilities,

1) I'm sure there are plenty of apps out there that consider the
inability to read from stdin a fatal error. I can see all the bugs about
"my helper won't work with mozilla but it works with [browser of
choice]." Do you want to spend the time verifying which apps work?

2) There are any number of semi-broken apps that react weirdly when
stdin is closed. They often do go into infinite loops.

Actually, neither 1) or 2) do any good because any app can open the
magic /dev/tty. Think that password reading app again.

3) So maybe you now can't read at all from the terminal. Can't get that
pesky password. More bugs about broken mozilla. BTW, do you know which
signal handlers are reset on a fork-and-exec? Do you know that for all
unix-like platforms? What's to prevent an app from restoring default
signal handlers? See the problem?

If the thing that launches mozilla does something odd then I say it's
broken, not mozilla.
If an app restores default signal handlers, would that not only affect the app 
and not Mozilla proper?

Garth, what happens if you try to use ghostscript as a helper in other 
browsers, out of curiousity?
Netscape 4.78, with ghostscript set as the handler for applicatin/postscript and
*.ps. Clicking on a link to a PostScript file causes the ghostscript window to
briefly appear, then disappear, and a dialog to appear. The title is "Netscape:
subprocess diagnostics (stdout/stderr)" and the body is as follows:

"GNU Ghostscript 6.51 (2001-03-28)
Copyright (C) 2001 artofcode LLC, Benicia, CA. All rights reserved.
This software comes with NO WARRANTY: see the file COPYING for details.
Loading NimbusRomNo9L-Regu font from
/usr/share/fonts/default/Type1/n021003l.pfb... 2362024 982784 1622424 328124 0 done.
Loading NimbusSanL-Regu font from /usr/share/fonts/default/Type1/n019003l.pfb...
2639936 1238459 1642520 335588 0 done.
GS>

[OK]"

It appears that Netscape catches the TTY output of ghostscript and displays it
in a dialog, but kills the subprocess when it tries to read from stdin. So it
doesn't display the PS file, but it also doesn't freeze Netscape.
Ah, right.  Netscape actually redirects stdin and stdout, which it can do 
because it doesn't spew shit to stdout all the time like Mozilla does....

I'm semi-tempted to try and replicate the Netscape behavior.  I would rather 
have helpers not work than have the browser hang. 
> I'm semi-tempted to try and replicate the Netscape behavior.  I would
> rather have helpers not work than have the browser hang.

Unless you're willing to install prefs to undo this, resist the
temptation. After you've seen 20 or more dialogs from a helper, it gets
really boring.

There's also no spec on what constitutes an "acceptable" helper (I'm not
sure there can or should be) so implicitly rejecting helpers seems rude.

Also, mozilla's inability to pass parameters to helpers makes this
worse.

Now, if you could redirect stdin/stdout/stderr on a per-helper basis
that might be nice.
futuring pending any clues as to how to actually handle this gracefully
Priority: P1 → P3
Target Milestone: mozilla1.1beta → Future
I agree this is hard and requires thought but did the relnote ever
happen?
No, it did not.  Would you mind writing one and mailing it to
endico@mozilla.org, with a pointer to this bug?  I won't be able to do it for a
bit; kinda swamped with things....
How does this wording grab you ?

  A helper application that attempts to communicate with the user 
  directly through the terminal (rather than through a dialog box)
  may cause mozilla to stop if mozilla is running as a background 
  process. (This is a common Unix restriction. Background processes
  and their children are not allowed terminal access and every one
  of these processes will stop if any one of them tries.)

  If possible, it is best to use a helper that does not communicate via 
  the terminal. For example, use "gv" rather than "gs" to view
  PostScript documents. If not possible, then mozilla must run as a
  foreground process. In case mozilla is stopped, see the job control 
  documentation for your shell for information on how to continue a job
  in the foreground.

Maybe it's too verbose.
jatin: comments? I'm willing to add that text as is, although I do believe it 
is too verbose.

Reading back through the comments, i believe that the relnote should mention 
needs terminal, or maybe that's only useful when it works? If that doesn't work 
yet, how hard would it be to implement?
Keywords: relnote
That's only useful when it works. It's not hard to implement; it's _that_ hard
to implement such that it'll work on all the various platforms we stuff through
the "unix" codepath....

I may end up assuming existence of "sh" and "xterm" and just doing it...  Then
we can update the relnote.
QA Contact: sairuh → petersen
Priority: P3 → P5
*** Bug 208755 has been marked as a duplicate of this bug. ***
Depends on: 147659
No plans to work on this any time in the foreseeable future, so to default owner.
Assignee: bz-vacation → file-handling
QA Contact: chrispetersen → ian
Priority: P5 → --
Target Milestone: Future → ---
taking
Assignee: file-handling → cbiesinger
Target Milestone: --- → mozilla1.8alpha
Attached patch patch (obsolete) — Splinter Review
how about this?
(In reply to comment #18)
> Mozilla shouldn't mess with stdin, etc. I can easily imagine a helper
> app that would want to talk to the terminal. Maybe it wants a password
> before continuing, maybe something else.

most users do not run mozilla from a terminal. so if they set a helper app that
wants to read from a terminal, they have no way to give that input...
Comment on attachment 140838 [details] [diff] [review]
patch

We should just do this instead of pretending this is not a problem.  At least
this way the helper is likely to give the user a useful error message.

r=bzbarsky
Attachment #140838 - Flags: review+
Status: NEW → ASSIGNED
No longer depends on: 147659
Target Milestone: mozilla1.8alpha → mozilla1.7alpha
Just closing stdin is a bad idea because the kernel will reuse that fd on the 
next file op. You could have a child process or a plugin thinking stdin is 
something it isn't. It would be better to open /dev/null and dup that fd to 
stdin. Daemons do this.
As bz said in comment #21, reproducing the old Netscape behavior may be best. 
Presumably that's in the earliest mozilla code. Does anyone know where? Also, 
maybe just do this in a non-debug build. I don't care if developers lock 
themselves up.
Summary: Mozilla freeze when using ghostscript to read link → freeze when helper app reads from stdin (e.g. ghostscript)
Using this code which ignores SIGTTIN, I saw that ^Z can still stop the process
(as expected), so if we went that route, mozilla could still be suspended with
^Z like a normal app.  However, the getchar() did not result in a pause, and
returned -1.  That would probably break helper apps like ghostscript.

#include <stdio.h>
#include <signal.h>

int main()
{
  sigset_t sigs;
  int junk;
  sigaddset(&sigs, SIGTTIN);

  sigprocmask(SIG_BLOCK, &sigs, NULL);
  printf("hello, world!\n");
  junk = getchar();
  printf("%d\n", junk);

  while(1)
    {
      printf("a"); // putting some sort of delay here, e.g. sleep()
                   // would make this friendlier
    }
  return 0;
}
*** Bug 234780 has been marked as a duplicate of this bug. ***
Comment on attachment 140838 [details] [diff] [review]
patch

obsoleting per comment 35
Attachment #140838 - Attachment is obsolete: true
Attachment #140838 - Flags: superreview?(jag)
Attachment #143829 - Flags: superreview?(jag)
Attachment #143829 - Flags: review?(bzbarsky)
Comment on attachment 143829 [details] [diff] [review]
like this, then

Yeah, ok.
Attachment #143829 - Flags: review?(bzbarsky) → review+
Comment on attachment 143829 [details] [diff] [review]
like this, then

Sure, this works, though since you're only #include'ing stdio.h for XP_UNIX,
add it inside the #ifdef.
Attachment #143829 - Flags: superreview?(jag) → superreview+
For generality you should use the _PATH_DEVNULL macro from paths.h if it 
exists, i.e.:

#include <paths.h>
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif

Also, using stdio incurs some extra overhead. Usually you see calls to the 
lower level open which also allows more paranoia, like using O_NOFOLLOW if 
it's avaliable.
If there are other threads running I think you need to put a lock around the 
code that redirects stdin. Also, are you sure no one else may have started to 
read from stdin when you do this?  You're pulling the rug out from under them 
and bad things may happen.
(In reply to comment #44)
> If there are other threads running 

what, at about the 4th line in main()?
> what, at about the 4th line in main()?

Probably safe then unless something weird happens in the constructors.
Here's a dumb question. Since this is unix only and unix starts with shell
scripts why not just change the mozilla scripts so it does "run-mozilla.sh
</dev/null"?
hm, sure, that would be doable. but I believe bsmedberg would like to get rid of
the script. bsmedberg, can you comment? (in reply to comment 47)
Well, hmm. It is in the works to remove the shell scripts from the new-toolkit
apps, so I don't like bugfixes that rely on them. But I don't understand all the
issues, and as a hacky-fix it looks fairly safe and elegant ;)
Benjamin Smedbergwrote:
> Well, hmm. It is in the works to remove the shell scripts from the new-toolkit
> apps,

Do you want to get rid of the shell scripts which start *Bird/*Fox/etc. ? If
"yes"... how do you want to do that ? You can't set LD_*-vars from within the
application...
I'm all for removing the shell scripts on security issues alone but it
requires copperation with the underlying OS. This is something mozilla doesn't
seem to like to do. See bug 57866 for a really old proposal I had for a
launcher program. See also bug 125505 for an almost as old companion to
properly exit the mozilla environment. Where is this being discussed?

As I see it, this bug is about mozilla avoiding a standard security 
precaution. There's no actual bug here. The more I think about it the more I 
think this is a question for the embedder/packager/distributor and not 
mozilla. Besides, you can't guarantee proper redirection in all cases unless 
you do it between a fork and exec.
 
mozhack@boffo:~/obj-i686-pc-linux-gnu-xlib/dist/bin$ ./run-mozilla.sh -g -d gdb
./regxpcom  < /dev/null
MOZILLA_FIVE_HOME=.
  LD_LIBRARY_PATH=.:./plugins:.
DYLD_LIBRARY_PATH=.:.
     LIBRARY_PATH=.:./components:.
       SHLIB_PATH=.:.
          LIBPATH=.:.
       ADDON_PATH=.
      MOZ_PROGRAM=./regxpcom
      MOZ_TOOLKIT=
        moz_debug=1
     moz_debugger=gdb
/usr/bin/gdb ./regxpcom -x /tmp/mozargs6794
GNU gdb 5.2
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-slackware-linux"...
(gdb) mozhack@boffo:~/obj-i686-pc-linux-gnu-xlib/dist/bin$

if we go the redirect route, it is a bit more work than just </dev/null, because
we just doing that will break gdb.

and of course ./run-mozilla.sh ./xpcshell </dev/null would be bad...
If you're debugging I see no reason why you would want stdin redirected 
anyway. Presumably (and it's a big assumption I suppose) you understand the 
consequences.

Note that I said the mozilla script _not_ run-mozilla.sh. I did think about 
regxpcom, etc.
the problem with this is that -g now *significantly* changes the behavior of a
running mozilla. this is a bad thing.

i suppose an alternative would be for someone to teach me how to get gdb to run
an app w/ </dev/null, and then i'd teach run-mozilla.sh about -noinput or
something...
You got there before me. :-) I had

Index: mozilla/xpfe/bootstrap/mozilla.in
===================================================================
RCS file: /cvsroot/mozilla/xpfe/bootstrap/mozilla.in,v
retrieving revision 1.6
diff -u -r1.6 mozilla.in
--- mozilla/xpfe/bootstrap/mozilla.in   20 Feb 2004 18:13:46 -0000      1.6
+++ mozilla/xpfe/bootstrap/mozilla.in   29 Mar 2004 18:52:59 -0000
@@ -157,11 +157,13 @@
 ## Start addon scripts
 moz_pis_startstop_scripts "start"

+STDIN_REDIR="</dev/null"
 if [ $debugging = 1 ]
 then
   echo $dist_bin/run-mozilla.sh $script_args $dist_bin/$MOZILLA_BIN "$@"
+  STDIN_REDIR=
 fi
-"$dist_bin/run-mozilla.sh" $script_args "$dist_bin/$MOZILLA_BIN" "$@"
+"$dist_bin/run-mozilla.sh" $script_args "$dist_bin/$MOZILLA_BIN" "$@" 
$STDIN_REDIR
 exitcode=$?

 ## Stop addon scripts

In gdb just add the redirection into the "set args" command, /tmp/mozargs* 
would then have

    set args "stuff" </dev/null
It occurred to me that we've only heard from poeple who think it's a bad idea
to have stdin be a terminal. There may well be other poeple out there with
helper apps that rely on this. We may well need a something like a
-no-stdin-redirect option to be safe.
This bug has been plaguing me for some time. Especially on recent builds of
Firefox, where clicking on a link to a file of type text/x-patch gives me the
open dialog box with "Open With: less (default)" which of course freezes the
browser immediately (when operating the browser from the background). It seems
to me an additional option (have the browser attempt to render it -- it is text
after all) would be nice. Wouldn't help for things like gs, but...
Less opens /dev/tty directly so _any_ background process that invokes it will 
freeze. Mozilla can do nothing about this.
since there seems to be disagreement about whether that patch is the right
thing, -> default owner
Assignee: cbiesinger → file-handling
Status: ASSIGNED → NEW
Target Milestone: mozilla1.7alpha → ---
Assignee: file-handling → nobody
QA Contact: ian → file-handling
Keywords: relnote
Product: Core → Firefox
Version: Trunk → unspecified
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: