Running in the background (via &)

M

Mark Seger

I have the following simple script.

#!/usr/bin/perl -w
print `resize`;

If I run it in the foreground it works just fine, but if I run it in the
background it hangs until I foreground it. Is there a way to tell if
you're running in the background - it may be a UNIX feature that you
cannot. Otherwise, is there some way to diddle the environment (perhaps
redirecting file descriptors) so it won't hang?

-mark
 
J

Josef Moellers

Mark said:
I have the following simple script.

#!/usr/bin/perl -w
print `resize`;

If I run it in the foreground it works just fine, but if I run it in the
background it hangs until I foreground it. Is there a way to tell if
you're running in the background - it may be a UNIX feature that you
cannot.

In a sense: you cannot as in *ix there is actually no conceptual
difference between a "foreground" and a "background" process.

The terms "foreground" and "background" are used to distinguish between
processes that the shell waits for and those that the shell doesn't wait
for (e.g. thos started with an ampersand). So it's the parent who
defines whether a process is a background process or a foreground
process and then, even that may change, e.g. if you start a process, do
quite a lot of different stuff (the new process could then be viewed as
running in the background), then wait for the process (it might then be
seen as a foreground process) until you are taken out of the wait() by a
signal, and continue (which would turn your process into a background
process again).
Also with some shells you can actively change processes between fore-
and background.
Otherwise, is there some way to diddle the environment (perhaps
redirecting file descriptors) so it won't hang?

Would it help to have an indication whether you're in the foreground or
in the background?
Usually background processes aren't connected to a terminal, most
important, STDIN won't be connected to a terminal as then two processes
(the current "foreground" process and the "background" process) contend
for the input from the keyboard, so you could check whether STDIN is a
terminal.
This will fail if you have a foreground process that has stdin
redirected from a file or from a pipe, though.

HTH,

Josef
 
M

Mark Seger

\
Would it help to have an indication whether you're in the foreground or
in the background?
Usually background processes aren't connected to a terminal, most
important, STDIN won't be connected to a terminal as then two processes
(the current "foreground" process and the "background" process) contend
for the input from the keyboard, so you could check whether STDIN is a
terminal.
that's what I thought and so did a -t STDIN, but it shows true whether
in the foreground or background.
-mark
 
M

Mark Seger

I have a solution, based on an example in the perl cookbook by calling
iloctl directly to get the terminal height and it seems to work in both
foreground and background. Can I count on the ioctls.ph file being
present in asm? Is there somewhere else I should look for it?

#!/usr/bin/perl -w
require "asm/ioctls.ph";
my $winsize="\0" x 8;
if (ioctl(STDOUT, TIOCGWINSZ(), $winsize)) {
($rows)=(unpack('S4', $winsize))[0];
}
else {
print "ERROR\n";
}
print "rows: $rows\n";

-mark
 
P

Peter J. Holzer


This is wrong in general.

That's why about 20 years ago, Unixes started to stop background
processes from reading from the terminal (see the SIGTTIN signal).

Won't work.
that's what I thought and so did a -t STDIN, but it shows true whether
in the foreground or background.

Right. STDIN doesn't change. You can flip a process between foreground
and background (in most shells with the conveniently named commands "fg"
and "bg"), but it would be rather messy if that changed an open file
descriptor. What changes is whether the process group is the foreground
process group of the controlling terminal. The place to look for
POSIX (=UNIX) specific functionality is the POSIX module:

| getpgrp This is identical to Perl’s builtin "getpgrp()" function for
| returning the process group identifier of the current process,
| see "getpgrp" in perlfunc.
[...]
| tcgetpgrp
| This is identical to the C function "tcgetpgrp()" for returning
| the process group identifier of the foreground process group of
| the controlling terminal.

If they are the same we should be in the foreground:

% perl -MPOSIX -le 'print getpgrp() == tcgetpgrp(STDIN) ? "foreground" : "background"'
foreground

% perl -MPOSIX -le 'print getpgrp() == tcgetpgrp(STDIN) ? "foreground" : "background"' & sleep 1
[1] 23462
background
[1] + done perl -MPOSIX -le

Looks good.

hp
 
C

comp.lang.c++


This is wrong in general.

That's why about 20 years ago, Unixes started to stop background
processes from reading from the terminal (see the SIGTTIN signal).

Won't work.
that's what I thought and so did a -t STDIN, but it shows true whether
in the foreground or background.

Right. STDIN doesn't change. You can flip a process between foreground
and background (in most shells with the conveniently named commands "fg"
and "bg"), but it would be rather messy if that changed an open file
descriptor. What changes is whether the process group is the foreground
process group of the controlling terminal. The place to look for
POSIX (=UNIX) specific functionality is the POSIX module:

| getpgrp This is identical to Perl’s builtin "getpgrp()" functionfor
| returning the process group identifier of the current process,
| see "getpgrp" in perlfunc.
[...]
| tcgetpgrp
| This is identical to the C function "tcgetpgrp()" for returning
| the process group identifier of the foreground process group of
| the controlling terminal.

If they are the same we should be in the foreground:

% perl -MPOSIX -le 'print getpgrp() == tcgetpgrp(STDIN) ? "foreground" : "background"'
foreground

And, POSIX misses if stdin/stdout are redirected:

perl -MPOSIX -le 'warn getpgrp()==tcgetpgrp(STDIN)
? foreground" : "background"' </dev/null >/dev/null
background at -e line 1.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,778
Messages
2,569,605
Members
45,238
Latest member
Top CryptoPodcasts

Latest Threads

Top