Bug 50774

Summary: variables trashed in forked process
Product: [Retired] Red Hat Linux Reporter: Dan Mergens <dan>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact: David Lawrence <dkl>
Severity: medium Docs Contact:
Priority: medium    
Version: 7.0   
Target Milestone: ---   
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2001-08-03 00:09:45 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Dan Mergens 2001-08-03 00:09:41 UTC
From Bugzilla Helper:
User-Agent: Mozilla/4.76 [en] (X11; U; Linux 2.2.16-22 i686)

Description of problem:
When setting a variable in a forked process, its value is not set properly.

How reproducible:
Always

Steps to Reproduce:
Here's the source code to compile and run
----------------------------------------
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define REDIRECT_BUFFER_SIZE 1000000

/*----------------------------------------------------------------------
FUNCTION
        redirectIO - capture the standard output of a spawned process
SIDE EFFECTS
        Allocates memory for return character array which must be freed
        by calling process.
LIMITATIONS
        The buffer size is limited to REDIRECT_BUFFER_SIZE bytes for the
        standard output.
----------------------------------------------------------------------*/
char* redirectIO( const char* arglist, int* status=NULL );
 
char*
redirectIO( const char* arglist, int* status )
{
        int   fds[2];
        int   nread;
        pid_t pid;
        char* buf = (char*)malloc( sizeof(char)*REDIRECT_BUFFER_SIZE );
 
        pipe( fds );
 
        pid = fork();
        if( pid == 0 )  // child process
        {
                close( 1 );
                dup( fds[1] );
                close( fds[0] );
                if( status != NULL )
                        *status = system( arglist );
                else
                        system( arglist );
                exit( EXIT_SUCCESS );
        }
        else
        {
                nread = read( fds[0], buf, REDIRECT_BUFFER_SIZE );
                if( nread < REDIRECT_BUFFER_SIZE )
                {
                        buf = (char*)realloc( buf, sizeof(char)*(nread+1)
);
                        buf[nread] = 0;
                }
                else if( nread >= (REDIRECT_BUFFER_SIZE-1) )
                {
                        buf[REDIRECT_BUFFER_SIZE-1] = 0;
                }
        }
 
        return buf;
}
 
int main( int argc, char* const* argv )
{
        char*  return_string;
        int    status;
 
//      status = system( "wc -l testfile.txt" );
        return_string = redirectIO( "wc -l testfile.txt", &status );
        fprintf( stdout, "return string is %s\n", return_string );
        fprintf( stdout, "status is %d\n", status );
}
--------------------------------------------------
(You will also need the file testfile.txt which is only used for the line
count)

Actual Results:  return string is       2 testfile.txt
 
status is 134514545

Expected Results:  return string is       2 testfile.txt
 
status is 0

Additional info:

When the system call is performed in a function or in the main block the
status is set correctly to 0. This code works on IRIX properly. Apparently,
the variable either getting trashed or not set in the forked process.

Comment 1 Jakub Jelinek 2001-08-06 15:04:45 UTC
This is the expected behaviour. fork means the two processes don't share
address space, so writing into *status in the child really should not do
anything in the parent (it is possible that this was 0 on Irix before).
If you want the two processes to share memory, so that this would work,
please check out POSIX threads library or clone system call instead.