Thread: pipes between child and parent

  1. #1
    Registered User
    Join Date
    Dec 2010
    Posts
    6

    pipes between child and parent

    Hi,
    Im trying to do a simple program which fork. The parent process sends data to the child process via a pipe and collect data from the child via an other pipe.

    The child process redirect the input and output and call execvp with the command specified by the user when he run the program (argv[]).

    My program work well with basic commands like ls or echo but is stuck somewhere when i use commands that needs basic interaction with the user like tr a-z A-Z.

    I also use poll() in the parent process to monitor between stdin and what the child process send but I don't think this is the problem. I think it's more about a broken pipe or a write that block.

    I spent all day looking all over the internet looking for a solution. Any help would be appreciated thanks

    Code:
    void executerCommande( char *commande[], int descripteur, char* option )
    {
    	int tubeEntree[2];
    	int tubeSortie[2];
    	int erreur;
    	
    	erreur = pipe( tubeEntree );
    	if ( erreur == -1 )
    	{
    		printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
    		exit( 1 );
    	}
    	erreur = pipe( tubeSortie );
    	if ( erreur == -1 )
    	{
    		printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
    		exit( 1 );
    	}
    
    	pid_t pid = fork();
    	if ( pid == -1 )	// erreur
    	{
    		perror( "fork a échoué" );
    		exit( 1 );
    	}
    	else if ( pid == 0 )	// child
    	{
    		close( tubeEntree[1] );		// closing writing end of tube from parent to child
    		close( tubeSortie[0] );		// closing reading end of tube from child to parent
    		
    		dup2( tubeSortie[1], 1 );	// redirecting stdout to writing end of tube from child to parent
    		close( tubeSortie[1] );		// fermeture du doublon
    		
    		dup2( tubeEntree[0], 0 );	// redirecting stdin to reading end of tube from parent to child
    		close( tubeEntree[0] );		// fermeture du doublon
    		execvp( commande[0], commande );
    	}
    	else		// parent
    	{
    		int evenement;
    		int commandeTerminee = 0;
    		char tampon [256];
    		struct pollfd entrees[2];
    		entrees[0].fd = 0;		// check stdin
    		entrees[0].events = POLLIN | POLLPRI;		// surveiller pour des données normales ou prioritaires
    		entrees[0].revents = 0;
    		entrees[1].fd = tubeSortie[0];		// check reading end of tube from child to parent
    		entrees[1].events = POLLIN | POLLPRI;		// surveiller pour des données normales ou prioritaires
    		entrees[1].revents = 0;
    
    		close( tubeEntree[0] );		// closing reading end of tube from parent to child
    		close( tubeSortie[1] );		// closing writing end of tube from child to parent
    		
    		while ( commandeTerminee == 0 )
    		{
    			entrees[0].revents = 0;
    			entrees[1].revents = 0;
    			evenement = poll( entrees, 2, 0 );
    			if ( evenement == -1 )
    			{
    				printf( "Erreur lors du poll %s\n", strerror( errno ) );
    				exit( 1 );
    			}
    			if ( ( entrees[0].revents & POLLIN ) || ( entrees[0].revents & POLLPRI ) )
    			{
    				memset(tampon, '\0', 256);
    				read( entrees[0].fd, tampon, 256 );
    				erreur = write ( tubeEntree[1], tampon, strlen( tampon ) );
    				if ( erreur == -1 )
    				{
    					printf( "Erreur lors de l'écriture dans le tube d'entrée %s\n", strerror( errno ) );
    					exit( 1 );
    				}
    			}
    			if ( ( entrees[1].revents & POLLIN ) || ( entrees[1].revents & POLLPRI ) )
    			{
    				do {
    					memset(tampon, '\0', 256);
    					erreur = read( entrees[1].fd, tampon, 256 );
    					if ( erreur == -1 )	
    					{
    						printf( "Erreur lors de la lecture du tube de sortie %s\n", strerror ( errno ) );
    						exit( 1 );
    					}
    					printf( "%s", tampon );
    				} while (erreur != 0);
    			}
    			if ( entrees[1].revents & POLLHUP )
    			{
    				printf( "recu terminaison\n" );
    				commandeTerminee = 1;
    			}
    		}	
    		pid = wait( NULL );
    	}
    }

  2. #2
    Registered User
    Join Date
    Dec 2010
    Posts
    6
    I will make everyone that can help me RICH #letsWorkOnThisTogether

  3. #3
    Registered User
    Join Date
    Dec 2010
    Posts
    10

    mabey

    i'm not sure but just to be sure add check to the close sys call and the dup2 like you wrote to the pipe and fork

  4. #4
    Registered User
    Join Date
    Dec 2010
    Posts
    6
    I check the return value of close and dup2 and everything seems ok but thnx

  5. #5

  6. #6
    Registered User
    Join Date
    Dec 2010
    Posts
    10
    execvp( commande[0], commande[0],NULL );

  7. #7
    Registered User
    Join Date
    Dec 2010
    Posts
    6
    You can't see it on the code but i make sure that commande in my example is ending by NULL. As i said this program works perfectly with ls, echo, date, cat, etc. Just tr and the commands that interact with the user as long as he doesnt press ^D or ^C. I think its more a pipe problem because if i dont redirect the standard output of the child in the tube (tubeSortie[1]), It works. I need to redirect this entry to save the result in a file.

  8. #8
    Registered User
    Join Date
    Dec 2010
    Posts
    6
    I check the return value of dup2 when I redirect stdout of the child in the pipe "tubeSortie[1]" and I get an error when executing the program. I don't close the pipe or stdout before that so i dont know whats happening. Im using mac os x under darwin
    Code:
    void executerCommande( char *commande[], int descripteur, char* option )
    {
    	int tubeEntree[2];
    	int tubeSortie[2];
    	int erreur;
    	
    	erreur = pipe( tubeEntree );
    	if ( erreur == -1 )
    	{
    		printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
    		exit( 1 );
    	}
    	erreur = pipe( tubeSortie );
    	if ( erreur == -1 )
    	{
    		printf( "Erreur lors de la création du tube %s\n", strerror( errno ) );
    		exit( 1 );
    	}
    
    	pid_t pid = fork();
    	if ( pid == -1 )	// erreur
    	{
    		perror( "fork a échoué" );
    		exit( 1 );
    	}
    	else if ( pid == 0 )	// child
    	{
    		erreur = close( tubeEntree[1] );		// closing writing end of tube from parent to child
    		if ( erreur == -1 )
    		{
    			printf( "Erreur lors du close %s\n", strerror( errno ) );
    			exit( 1 );
    		}
    		erreur = close( tubeSortie[0] );		// closing reading end of tube from child to parent
    		if ( erreur == -1 )
    		{
    			printf( "Erreur lors du close %s\n", strerror( errno ) );
    			exit( 1 );
    		}
    		if ( dup2 ( tubeSortie[1], 1 ) < 0 );	// redirecting stdout to writing end of tube from child to parent
    		{
    			printf( "Erreur lors du dup stdout %s\n", strerror( errno ) );
    			exit( 1 );
    		}

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 05-01-2011, 11:06 AM
  2. Why isn't the execlp() function doing anything?
    By jsrig88 in forum C Programming
    Replies: 5
    Last Post: 10-12-2009, 10:09 AM
  3. Replies: 3
    Last Post: 10-15-2008, 09:24 AM
  4. process programming
    By St0rM-MaN in forum Linux Programming
    Replies: 2
    Last Post: 09-15-2007, 07:53 AM
  5. pipe
    By smart girl in forum C Programming
    Replies: 4
    Last Post: 04-30-2006, 09:17 AM