For Programmers: Free Programming Magazines  


Home > Archive > Unix Programming > July 2007 > is there any diff of wait/fork in Hp Unix and linux









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author is there any diff of wait/fork in Hp Unix and linux
Manoj Jain

2007-07-12, 7:07 pm

Hi All

I ran a small code and i found that below code is behaving differently
in Hp Unix and Linux.

#include <stdio.h>
#include <signal.h>
void end(int);
int main()
{
int iStatus=0;
int iRet=0;
int pid=0;
iRet = wait(&iStatus);
printf ("iRet = %d\n", iRet);
pid = fork();
signal(SIGCHLD,end);
switch(pid)
{
case -1:
printf("FORK ERROR\n");
break;
case 0:
printf("child\n");
sleep(10);
_exit(0) ;
default:
printf ("parent\n");
break;
}
iRet = wait(&iStatus);
printf ("iRet in Main = %d\n", iRet);

}
void end(int abc)
{
int iStatus=0;
int iRet;
printf ("END OF SIGCHILD\n");
iRet = wait(&iStatus);
printf ("iRet in END = %d\n", iRet);
if (iRet > 0)
printf ("EXITING CHILD\n");
}
Output in Linux:
iRet = -1
child
parent
END OF SIGCHILD
iRet in END = -1
iRet in Main = 31219

Output in Hp Unix:
iRet = -1
parent
child
END OF SIGCHILD
iRet in END = 4280
EXITING CHILD
iRet in Main = -1


Why wait is returning different values in Both env??

THanks in advance.

Jens Thoms Toerring

2007-07-12, 7:07 pm

Manoj Jain <manojsamar@gmail.com> wrote:
> I ran a small code and i found that below code is behaving differently
> in Hp Unix and Linux.


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


You forgot

#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

> void end(int);
> int main()
> {
> int iStatus=0;
> int iRet=0;
> int pid=0;
> iRet = wait(&iStatus);
> printf ("iRet = %d\n", iRet);
> pid = fork();
> signal(SIGCHLD,end);


You should definitly move that line to before the fork(), other-
wise the child process may already be dead (if, for example, you
remove the sleep() call in the child()) before te parent has time
to install its signal handler!

> switch(pid)
> {
> case -1:
> printf("FORK ERROR\n");
> break;
> case 0:
> printf("child\n");
> sleep(10);
> _exit(0) ;
> default:
> printf ("parent\n");
> break;
> }
> iRet = wait(&iStatus);
> printf ("iRet in Main = %d\n", iRet);


Since you promised that main() returns an int you should do so:

return 0;

> }
> void end(int abc)
> {
> int iStatus=0;
> int iRet;
> printf ("END OF SIGCHILD\n");
> iRet = wait(&iStatus);
> printf ("iRet in END = %d\n", iRet);
> if (iRet > 0)
> printf ("EXITING CHILD\n");
> }
> Output in Linux:
> iRet = -1
> child
> parent
> END OF SIGCHILD
> iRet in END = -1
> iRet in Main = 31219


> Output in Hp Unix:
> iRet = -1
> parent
> child
> END OF SIGCHILD
> iRet in END = 4280
> EXITING CHILD
> iRet in Main = -1


> Why wait is returning different values in Both env??


There are no guarantees made about the sequence the parent
and child process are run after fork(). It can even change
between different invocations of the same program;-) And
even if it's always the same on a certain operating system
it could easily change with the next version of the same
system (if I remember correctly this has at least happened
once for Linux). So you definitely shouldn't rely on any
assuptions.

The other question concerning which of your calls of wait()
actually reaps in the childs return status is again some-
thing you normally shouldn't be forced to make assumptions
about. As you see in Linux obviously the kernel is written
in a way that the first call of wait() "gets" the childs
exit status while under HP Unix wait() can become inter-
rupted by the signal handler before it "got" it and since
then in the signal handler calls wait() itself. The POSIX
standard says:

The wait() function shall suspend execution of the calling
thread until status information for one of the terminated
child processes of the calling process is available, or
until delivery of a signal whose action is either to exe-
cute a signal-catching function or to terminate the process.
If more than one thread is suspended in wait() or waitpid()
awaiting termination of the same process, exactly one thread
shall return the process status at the time of the target
process termination. If status information is available
prior to the call to wait(), return shall be immediate.

and further down:

If wait() or waitpid() returns because the status of a child
process is available, these functions shall return a value
equal to the process ID of the child process for which status
is reported. If wait() or waitpid() returns due to the delivery
of a signal to the calling process, -1 shall be returned and
errno set to [EINTR].

This makes it look as if the behaviour of HP Unix is the more
correct one (since the invocation of wait() outside the sig-
nal handler gets interrupted by the SIGCHLD signal this call
should return -1). But you probably can hardly change anything
about the behaviour of Linux (except modifying the kernel
yourself or complain on the kernel mailing list). So you
should better try to write your programs in a way that both
types of behaviour don't make a difference. Always assume
that a signal can come in at any moment - also at some time
during a function call - and avoid situations where the cor-
rect working of your program depends on something not being
interrupted by a non-blocked signal (this can admittedly
sometimes be difficult, and even figuring out that there's a
"race condition" can be far from non-trival).

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
Alex Fraser

2007-07-13, 8:06 am

"Jens Thoms Toerring" <jt@toerring.de> wrote in message
news:5fneenF3des9vU1@mid.uni-berlin.de...
[snip]
> There are no guarantees made about the sequence the parent
> and child process are run after fork(). It can even change
> between different invocations of the same program;-) And
> even if it's always the same on a certain operating system
> it could easily change with the next version of the same
> system (if I remember correctly this has at least happened
> once for Linux). So you definitely shouldn't rely on any
> assuptions.


I also remember a change in the order on Linux. Also, on a multiprocessor
system, both parent and child could run after fork().

> The other question concerning which of your calls of wait()
> actually reaps in the childs return status is again some-
> thing you normally shouldn't be forced to make assumptions
> about. As you see in Linux obviously the kernel is written
> in a way that the first call of wait() "gets" the childs
> exit status while under HP Unix wait() can become inter-
> rupted by the signal handler before it "got" it and since
> then in the signal handler calls wait() itself. The POSIX
> standard says:
>
> The wait() function shall suspend execution of the calling
> thread until status information for one of the terminated
> child processes of the calling process is available, or
> until delivery of a signal whose action is either to exe-
> cute a signal-catching function or to terminate the process.
> If more than one thread is suspended in wait() or waitpid()
> awaiting termination of the same process, exactly one thread
> shall return the process status at the time of the target
> process termination. If status information is available
> prior to the call to wait(), return shall be immediate.
>
> and further down:
>
> If wait() or waitpid() returns because the status of a child
> process is available, these functions shall return a value
> equal to the process ID of the child process for which status
> is reported. If wait() or waitpid() returns due to the delivery
> of a signal to the calling process, -1 shall be returned and
> errno set to [EINTR].
>
> This makes it look as if the behaviour of HP Unix is the more
> correct one (since the invocation of wait() outside the sig-
> nal handler gets interrupted by the SIGCHLD signal this call
> should return -1).


Yeah, the behaviour the OP found on Linux doesn't seem right (not an expert
on the internals but I think it happens because the signal is delivered
between wait() completing within the kernel, and returning to userspace).

Since generation of SIGCHLD and availability of the child's status happen at
the same time, it would be valid to see the wait() outside the signal
handler function return the status and the wait() in the signal handler
function indicate ECHILD, but only if they happen in that order (which they
don't with at least some versions of Linux).

In practice though, I can't see a use for calling wait() both inside and
outside the handler like the OP did. One or the other makes sense.

Alex


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com