Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

fork + exec and SIGSTOP/SIGCONT

912 views
Skip to first unread message

dmarkh

unread,
May 22, 2012, 2:54:36 PM5/22/12
to
This started out as the "Search for API function to activate a task
and return it's PID to the caller" thread.

As I said over there, the process of starting a task and obtaining
it's PID is
working using fork+exec as recommended. The reason I need the PID was
for some level of task managment. In particular, one thing I need to
be able to do is pause and continue these tasks using SIGSTOP/SIGCONT.
There are other things
also but this one seems to be giving me problems right now. When I
send SIGSTOP to one of these processes, it EXITS instead of pausing.
That same task pauses and continues just find when I send these
signals from a shell via "kill -s SIGSTOP/SIGCONT pid". In fact it
seems that if I send the signals from a different task (one that
didn't actually create the process) it works also? Why is the task
that
created the process not able to "correctly" send the SIGSTOP signal to
it? Sample code:

tskmgt.c : task that starts and attempts to pause another task

int32_t main(int argc, char **argv)
{
pid_t pid;
const char *path = "/home/markh/test/tsttsk";
char *arg = 0;

pid = fork();
if (pid == 0) { // then I am the new task
execv(path, &arg);
} else {
printf("PID of new task = %d\n", pid);
}
sleep(5);
printf("Sending SIGSTOP to pid %d\n", pid);
if (kill(pid, SIGSTOP) != 0)
perror("Failed to send SIGSTOP: ");
return 0;

}

tsttsk.c:

int32_t main(int argc, char **argv)
{
FILE *fd;
const char *path = "/var/log/srtl.log";
const char *mode = "w+";
fd = fopen(path, mode);
if (fd < 0) {
perror("fopen of /var/log/srtl.log failed: ");
return 1;
}
while (1) {
sleep(1);
fprintf(fd, "tsttsk is running\n");
fflush(fd);
}
return 0;

}

I attempted to use posix_spawn instead of fork+exec. It does the same
thing. When the task that started the other task sends the other task
a SIGSTOP signal, that other task EXITS instead of pausing. ????

Regards
Mark

Joshua Maurice

unread,
May 22, 2012, 3:09:37 PM5/22/12
to
On May 22, 11:54 am, dmarkh <dma...@cfl.rr.com> wrote:
[...]
> int32_t main(int argc, char **argv)
[...]
> int32_t main(int argc, char **argv)

Minor pedantic point. The return value of main should be "int", not
"int32_t".

Huibert Bol

unread,
May 22, 2012, 3:18:58 PM5/22/12
to
dmarkh <dma...@cfl.rr.com> wrote:

> When I
> send SIGSTOP to one of these processes, it EXITS instead of pausing.

Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
You might want to read up on "orphaned process groups".

--
Huibert
"Okay... really not something I needed to see." --Raven

dmarkh

unread,
May 22, 2012, 3:30:18 PM5/22/12
to
No, if I don't send the SIGSTOP, the task stays running. If I comment
out the SIGSTOP code, when I get a shell prompt back, I can pause and
continue the task "tsttsk" via "#kill -s SIGSTOP/SIGCONT pid". So the
task "tsttsk" is NOT exiting when the parent "tskmgt" exits. It exits
only when I send it a SIGSTOP.

Mark

Barry Margolin

unread,
May 22, 2012, 3:32:07 PM5/22/12
to
In article <jpgor2$s6j$1...@dont-email.me>,
Huibert Bol <huibe...@quicknet.nl> wrote:

> dmarkh <dma...@cfl.rr.com> wrote:
>
> > When I
> > send SIGSTOP to one of these processes, it EXITS instead of pausing.
>
> Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
> You might want to read up on "orphaned process groups".

This page looks like a pretty thorough explanation:

http://codeidol.com/unix/advanced-programming-in-unix/Process-Relationshi
ps/-9.10.-Orphaned-Process-Groups/

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Barry Margolin

unread,
May 22, 2012, 3:37:15 PM5/22/12
to
In article
<6a27e663-b028-41f0...@j3g2000yqb.googlegroups.com>,
dmarkh <dma...@cfl.rr.com> wrote:

> On May 22, 3:18 pm, Huibert Bol <huibert....@quicknet.nl> wrote:
> > dmarkh <dma...@cfl.rr.com> wrote:
> > > When I
> > > send SIGSTOP to one of these processes, it EXITS instead of pausing.
> >
> > Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
> > You might want to read up on "orphaned process groups".
>
> No, if I don't send the SIGSTOP, the task stays running. If I comment
> out the SIGSTOP code, when I get a shell prompt back, I can pause and
> continue the task "tsttsk" via "#kill -s SIGSTOP/SIGCONT pid". So the
> task "tsttsk" is NOT exiting when the parent "tskmgt" exits. It exits
> only when I send it a SIGSTOP.

Did you follow the URL I just posted? A process is only sent SIGHUP if
it's in an orphaned process group AND it's in the stopped state.

Change your test program so that the parent process doesn't exit, and
you should see that the child does NOT get killed when you send the
SIGSTOP.

dmarkh

unread,
May 22, 2012, 3:42:57 PM5/22/12
to
On May 22, 3:32 pm, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article <jpgor2$s6...@dont-email.me>,
>  Huibert Bol <huibert....@quicknet.nl> wrote:
>
> > dmarkh <dma...@cfl.rr.com> wrote:
>
> > > When I
> > > send SIGSTOP to one of these processes, it EXITS instead of pausing.
>
> > Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
> > You might want to read up on "orphaned process groups".
>
> This page looks like a pretty thorough explanation:
>
> http://codeidol.com/unix/advanced-programming-in-unix/Process-Relatio...
> ps/-9.10.-Orphaned-Process-Groups/
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***

The code is an example. In my real world the parent is not exiting. In
fact even the sample code provided, if I comment out the SIGSTOP code,
the child continues running after the parent exits, and I can then
pause/continue it (child) via "#kill -s SIGSTOP/SIGCONT pid". Why does
the child exit when I send it a SIGSTOP??

dmarkh

unread,
May 22, 2012, 3:47:13 PM5/22/12
to
On May 22, 3:37 pm, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article
> <6a27e663-b028-41f0-b5ef-043934518...@j3g2000yqb.googlegroups.com>,
>
>  dmarkh <dma...@cfl.rr.com> wrote:
> > On May 22, 3:18 pm, Huibert Bol <huibert....@quicknet.nl> wrote:
> > > dmarkh <dma...@cfl.rr.com> wrote:
> > > > When I
> > > > send SIGSTOP to one of these processes, it EXITS instead of pausing.
>
> > > Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
> > > You might want to read up on "orphaned process groups".
>
> > No, if I don't send the SIGSTOP, the task stays running. If I comment
> > out the SIGSTOP code, when I get a shell prompt back, I can pause and
> > continue the task "tsttsk" via "#kill -s SIGSTOP/SIGCONT pid". So the
> > task "tsttsk" is NOT exiting when the parent "tskmgt" exits. It exits
> > only when I send it a SIGSTOP.
>
> Did you follow the URL I just posted?  A process is only sent SIGHUP if
> it's in an orphaned process group AND it's in the stopped state.
>

> Change your test program so that the parent process doesn't exit, and
> you should see that the child does NOT get killed when you send the
> SIGSTOP.
>

My real program does just that and when it sends SIGSTOP to the child,
the child exits. Even if the parent does not exit, the child does when
it gets SIGSTOP. I've already done this with my real app and the test
code.

Mark

Huibert Bol

unread,
May 22, 2012, 3:53:18 PM5/22/12
to
dmarkh <dma...@cfl.rr.com> wrote:

> My real program does just that and when it sends SIGSTOP to the child,
> the child exits. Even if the parent does not exit, the child does when
> it gets SIGSTOP. I've already done this with my real app and the test
> code.

I can't speak for your real code, but in your test code the child
isn't killed until AFTER the parent exits.

Scott Lurndal

unread,
May 22, 2012, 3:56:27 PM5/22/12
to
Joshua Maurice <joshua...@gmail.com> writes:
however, since only the lower 8-bits of the return value are made
available via wait(2)/waitpid(2)/waitid(2), it really doesn't matter
how it is declared.

Not to mention that int and int32_t are the same on pretty much every
modern architecture (unless someone is still using a PDP-11).

scott

Scott Lurndal

unread,
May 22, 2012, 3:58:33 PM5/22/12
to
dmarkh <dma...@cfl.rr.com> writes:
>On May 22, 3:32=A0pm, Barry Margolin <bar...@alum.mit.edu> wrote:
>> In article <jpgor2$s6...@dont-email.me>,
>> =A0Huibert Bol <huibert....@quicknet.nl> wrote:
>>
>> > dmarkh <dma...@cfl.rr.com> wrote:
>>
>> > > When I
>> > > send SIGSTOP to one of these processes, it EXITS instead of pausing.
>>
>> > Actually, it gets killed (SIGHUP) by the kernel when it's parent exits.
>> > You might want to read up on "orphaned process groups".
>>
>> This page looks like a pretty thorough explanation:
>>
>> http://codeidol.com/unix/advanced-programming-in-unix/Process-Relatio...
>> ps/-9.10.-Orphaned-Process-Groups/
>>
>> --
>> Barry Margolin, bar...@alum.mit.edu
>> Arlington, MA
>> *** PLEASE post questions in newsgroups, not directly to me ***
>
>The code is an example. In my real world the parent is not exiting. In
>fact even the sample code provided, if I comment out the SIGSTOP code,
>the child continues running after the parent exits, and I can then
>pause/continue it (child) via "#kill -s SIGSTOP/SIGCONT pid". Why does
>the child exit when I send it a SIGSTOP??

What is the process exit status (see waitpid(2))?

Have you used strace/truss to trace the execution of the parent and the child?

(strace -f -o trace.output ./tskmgt)

scott

dmarkh

unread,
May 22, 2012, 3:56:54 PM5/22/12
to
On May 22, 3:53 pm, Huibert Bol <huibert....@quicknet.nl> wrote:
> dmarkh <dma...@cfl.rr.com> wrote:
> > My real program does just that and when it sends SIGSTOP to the child,
> > the child exits. Even if the parent does not exit, the child does when
> > it gets SIGSTOP. I've already done this with my real app and the test
> > code.
>
> I can't speak for your real code, but in your test code the child
> isn't killed until AFTER the parent exits.
>

It is killed before. Add a 60 seond delay to the end of the sample
code, after sending the SIGSTOP. During that 60 seonds try to find
"tsttsk". It's gone.

Mark

Huibert Bol

unread,
May 22, 2012, 4:03:18 PM5/22/12
to

One other thing:

dmarkh <dma...@cfl.rr.com> wrote:

> int32_t main(int argc, char **argv)
> {
> pid_t pid;
> const char *path = "/home/markh/test/tsttsk";
> char *arg = 0;
>
> pid = fork();
> if (pid == 0) { // then I am the new task
> execv(path, &arg);

Most programs expect at least one argument (the program name) and get
mightely confused, or even generate an exception, when called with zero.

dmarkh

unread,
May 22, 2012, 4:03:29 PM5/22/12
to
On May 22, 3:53 pm, Huibert Bol <huibert....@quicknet.nl> wrote:
> dmarkh <dma...@cfl.rr.com> wrote:
> > My real program does just that and when it sends SIGSTOP to the child,
> > the child exits. Even if the parent does not exit, the child does when
> > it gets SIGSTOP. I've already done this with my real app and the test
> > code.
>
> I can't speak for your real code, but in your test code the child
> isn't killed until AFTER the parent exits.
>

I just tried adding a long delay after sending the SIGSTOP. You are
right. The child stays running until the parent exits. So then the use
of fork-exec is not going to work for me? I need a method of starting
tasks within a program, being able to get their PIDs so that I can/
could send SIGSTOP/SIGCONT and other things also. How does the shell
do this?

Mark

Scott Lurndal

unread,
May 22, 2012, 4:28:04 PM5/22/12
to
dmarkh <dma...@cfl.rr.com> writes:
man 2 setsid
man 2 setpgid
man 2 tcsetpgrp

If you can find a copy of Tim William's _Session management in SVR4_, it goes
into all the gory details.

s

dmarkh

unread,
May 22, 2012, 4:14:35 PM5/22/12
to
Also, if the parent does not send SIGSTOP and just exits, the child
stays running and I can "kill -s SIGSTOP/SIGCONT pid" all day long.
Why does that work and how can I duplicate this behavior?

Mark

Scott Lurndal

unread,
May 22, 2012, 4:33:56 PM5/22/12
to
dmarkh <dma...@cfl.rr.com> writes:
Tim's paper on session management is not online. You can order it for
$5.00 from usenix.org.


Author: Tim Williams
Title: Session Management in System V Release 4
Pages: 365-375
Publisher: USENIX
Proceedings: USENIX Conference Proceedings
Date: Winter 1989
Location: San Diego, CA
Institution: AT&T Bell Laboratories, Summit

In the mean time, check http://en.wikipedia.org/wiki/Process_group

scott

Joshua Maurice

unread,
May 22, 2012, 5:53:52 PM5/22/12
to
On May 22, 12:56 pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
> Joshua Maurice <joshuamaur...@gmail.com> writes:
> >On May 22, 11:54=A0am, dmarkh <dma...@cfl.rr.com> wrote:
> >[...]
> >> int32_t main(int argc, char **argv)
> >[...]
> >> int32_t main(int argc, char **argv)
>
> >Minor pedantic point. The return value of main should be "int", not
> >"int32_t".
>
> however, since only the lower 8-bits of the return value are made
> available via wait(2)/waitpid(2)/waitid(2), it really doesn't matter
> how it is declared.

I'd be hesitant to conclude this. Big-endian and little-endian, just
for starters.

> Not to mention that int and int32_t are the same on pretty much every
> modern architecture (unless someone is still using a PDP-11).

True.

Barry Margolin

unread,
May 23, 2012, 10:52:32 AM5/23/12
to
In article
<b466e6a7-293b-4f9d...@e3g2000yqm.googlegroups.com>,
The shell doesn't normally exit while the process is stopped, it sticks
around so you can run commands like "fg" and "bg" to resume it.

Try this:

sleep 500
Ctl-z
jobs -l
logout

When you try to logout, the shell will presumably warn that you have a
stopped job. Logout again to confirm that you really want to do it.

Log back in, and use "ps x" to see if the PID of the sleep process
(which was shown in the jobs -l output) is still there. It won't be,
because when the shell exited it became an orphaned process group and
was killed.

dmarkh

unread,
May 23, 2012, 2:37:53 PM5/23/12
to
On May 23, 10:52 am, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article
> <b466e6a7-293b-4f9d-976d-ff3118623...@e3g2000yqm.googlegroups.com>,
Yep, your right. My test case was flawed from the beginning. I think I
may have been pointed to methods to get around it though. And my real
world tstmgt task when complete, might be hanging around for ever
anyway.

Anyway, Ttanks all, for all your help and I'm sorry if I seemed
somewhat hard headed.
You've all been very helpful to me

Regards
Mark

Geoff Clare

unread,
May 24, 2012, 8:13:07 AM5/24/12
to
Scott Lurndal wrote:

> Joshua Maurice <joshua...@gmail.com> writes:
>>On May 22, 12:56=A0pm, sc...@slp53.sl.home (Scott Lurndal) wrote:
>>> Joshua Maurice <joshuamaur...@gmail.com> writes:
>>> >On May 22, 11:54=3DA0am, dmarkh <dma...@cfl.rr.com> wrote:
>>> >[...]
>>> >> int32_t main(int argc, char **argv)
>>>
>>> >Minor pedantic point. The return value of main should be "int", not
>>> >"int32_t".
>>>
>>> however, since only the lower 8-bits of the return value are made
>>> available via wait(2)/waitpid(2)/waitid(2), it really doesn't matter
>>> how it is declared.
>>
>>I'd be hesitant to conclude this. Big-endian and little-endian, just
>>for starters.
>
> Endianess doesn't matter in this case. The WEXITSTATUS() macro will
> return the least significant 8 bits, regardless of the endianess of
> a machine word.

That's not where the problem would arise, if it does. The program
start-up code calls main() and expects it to return an int. It will
use the value it gets back from main() to set the process's exit status.

If main() has been defined with a different type, the code that called
it might get the wrong value, and use that wrong value to set the
exit status.

--
Geoff Clare <net...@gclare.org.uk>

0 new messages