LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 01-24-2008, 02:45 PM   #1
chudzielec
LQ Newbie
 
Registered: Oct 2006
Posts: 5

Rep: Reputation: 0
Question [C] stdout and stdin replace by pipes and execve the child


I've managed to create pipe between two processes. I can make parent's stout child's stdin but I cannot send EOF to child.

Here is the code
Edit: looks like rafb.net have forgotten about my code, so I've used wklej.org (but tabs are gone)
http://wklej.org/id/ca1f2b983b

My target is to make progress bar for tar application without knowing what is inside the archive file. I only know its name and size. The solution is to read tar archive byte after byte and send read values as stdin to tar. In simply way it can be done by that way:

cat archive.tar | tar xz

By replacing cat with application that writes down how much bytes was read (writing to tar stdin actually blocks until tar unpacks sent data) I can make a progress bar. The reason why I'm not doing it using bash is that I'm writing library that shouldn't depend on shell or create and execute unnecessary script files.

Last edited by chudzielec; 01-26-2008 at 04:09 PM.
 
Old 01-24-2008, 11:25 PM   #2
nadroj
Senior Member
 
Registered: Jan 2005
Location: Canada
Distribution: ubuntu
Posts: 2,539

Rep: Reputation: 60
not sure if this helps, but this is from man execve (which is the 'back-end' to exec*):
Quote:
...
execve() does not return on success, and the text, data, bss, and stack
of the calling process are overwritten by that of the program loaded.
The program invoked inherits the calling process's PID, and any open
file descriptors that are not set to close on exec. ...
maybe when you exec, it uses actually stdin and not the file descriptor you used dup2 with?

have you tried using named pipes (see man fifo)? the advantage of FIFOs is that any programs on the same host can communicate, that is, without needing a parent-child relationship. i would guess that a call to exec* is destroying this link.
 
Old 01-26-2008, 10:37 AM   #3
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
I don’t know why, but your hyperlink is broken, and we can’t see the code.

Usually, to send the child an EOF, you would close the “write-end” of the pipe (and the next time the child tries to read from it, it will get EOF). If you close the “read-end” of the pipe first, then the parent is send SIGPIPE.

Also, the write() function should only block when the pipe is full (on linux a full pipe means 64kB pending for the “read-end”).

Btw nadroj, the exec function should keep the file descriptor open (that is the point).
 
Old 01-26-2008, 04:21 PM   #4
chudzielec
LQ Newbie
 
Registered: Oct 2006
Posts: 5

Original Poster
Rep: Reputation: 0
@osor: new hyperlink but with broken indent http://wklej.org/id/ca1f2b983b

I disabled the buffering in my code.

@nadjor: I'm pretty sure that file descriptor are kept (at least the ones that describes stdin, stdout and stderr). Try to execute my code without exec line or try to replace exec with /bin/echo ( `echo "hello" | echo` prints nothing ). cat application displays what it gets so it looks good. I will check named pipes and report any progress. Thanks for advice.
 
Old 01-26-2008, 05:20 PM   #5
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Quote:
Originally Posted by chudzielec View Post
@osor: new hyperlink but with broken indent http://wklej.org/id/ca1f2b983b

I disabled the buffering in my code.
I see the problem:
Code:
if( pid == 0 ) {
// I am child

close(fd[1]);

// connect pipe output to stdin
dup2( fd[0], 0 );

close(fd[0]);

// loading image of cat application
execl("/bin/cat", "cat", NULL);
 
// because of exec* will never gets here and below
// so this is the end of child code

} else {
The line in red must be inserted for your problem to go away. The reason is that the right before the exec, the child has these file descriptors open:
Code:
0  — a copy of the read end of the pipe
1  — the terminal (normal stdout)
2  — stderr (probably also the terminal)
3* — read end of the pipe
4* — write end of the pipe

*I base this on the fact that fd[0] should be 3 and fd[1] should be 4
So when you do the exec, the stdin and stdout work as expected. But when you close the write end of the pipe in the parent, you forget that there is a copy of it still open in the child. So when the child does a read(), then call will block, waiting for the child to write to the pipe (which is never going to happen). So the correct thing to do is to close the write end of the pipe as soon as you get into the child process. Basically, the reading the read end of a pipe will return EOF when and only when all copies of the write end of the pipe are closed. In your case, you had left one copy open.

As for the line in blue, it is not strictly necessary, but it is good style to close a file descriptor you don’t need. You can also insert a similar line after the other call to dup2 (on line 33). In a real-world situation, you would check that the return values of each of those system calls (including pipe(), fork(), and dup2()) is not -1 before continuing.
 
Old 01-26-2008, 05:31 PM   #6
osor
HCL Maintainer
 
Registered: Jan 2006
Distribution: (H)LFS, Gentoo
Posts: 2,450

Rep: Reputation: 78
Btw, have you seen the program bar?
 
Old 01-27-2008, 05:52 AM   #7
chudzielec
LQ Newbie
 
Registered: Oct 2006
Posts: 5

Original Poster
Rep: Reputation: 0
@osor: Thanks a lot! Works great. About that bar application, I'm writing a library so progress will be returned as callback.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to capture both stdin and stdout of a child process? jineshkj Linux - Software 2 04-21-2006 06:34 AM
Details of stdin and stdout pixellany Linux - Newbie 1 01-11-2006 01:21 PM
stdout stdin Furlinastis Linux - Newbie 3 08-11-2005 11:00 PM
redirecting stdin and stdout with pipes: convincing apps they're for a terminal? prell Programming 1 09-02-2004 06:38 AM
stdin -> port -> stdout acid_kewpie Linux - Networking 5 04-12-2002 06:01 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:26 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration