C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old June 7th, 2004, 10:02 AM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
fork() [intercept child process err to stdout]

i coded a shell, and as usual it has a runcommand() function that uses fork() and executes a command in the child while the parent waits or prints out process ID and doesn't wait if the user selected it to be background

now when the child has an error msg it prints it outto the stdout, the problem is my Prompt shows up b4 that happens and doesn't wait for the child to print errors.

here is the code:

PHP Code:
 int RunCommand(CommandTypecommand,bool mode
{
    
int pid;
    
int status;
    
    
// creates child process
    
pid fork();
    
// checks for error
    
if (pid 0
    {
        
cout<<"Error in the fork process."<<endl;
        return 
1;
    }
    else if (
pid == 0
    {
        
//Child code
        
int x execvp(command->namecommand->argv);
        if (
x<0
        {
        
cout<<PROMPT<<":"<<command->name<<": Command not found."<<endl;
        exit(
1);
        }
    }
    
    else 
    {
        if(
mode == FOREGROUND
        {
            
// Parent waits
            
while (wait(&status) != pid);
            return 
status;
        }
        else if(
mode == BACKGROUND)
        {
            
cout<<"Process ID for application "<<command->name<<": "<<pid<<endl;
            
cout<<"To terminate the application Type: kill "<<pid<<endl;
        }
        
    }
    return 
0;



and here is a sample output when i try to execute kwrite in the background after i have choosen a different set of icons for my KDE and obviously kwrite can't find his icon:

[nash - /home/ahmed/Desktop/Project]>kwrite &
Process ID for application kwrite: 2277
To terminate the application Type: kill 2277
[nash - /home/ahmed/Desktop/Project]>kdecore (KIconLoader): WARNING: Icon directory /usr/share/icons/slick/ group not valid.
kdecore (KIconLoader): WARNING: Icon directory /usr/share/icons/slick/ group not valid.


now what i need is, either a way to make the parent wait till the child flushes it's err to stdout or a way to redirect the err to the parent for processing instead of stdout.

Reply With Quote
  #2  
Old June 7th, 2004, 01:00 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 94
if you run a command in the b/g, that's what happens. if u want to redirect stderr stream to the parent, then create a set of pipes in the parent, then in the child, dup2 the write end of the pipe to stderr, and then the parent can read from the read end of pipe to get the errors.

Reply With Quote
  #3  
Old June 9th, 2004, 03:54 PM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Exclamation Hmmm!

Quote:
Originally Posted by infamous41md
if u want to redirect stderr stream to the parent, then create a set of pipes in the parent, then in the child, dup2 the write end of the pipe to stderr, and then the parent can read from the read end of pipe to get the errors.


Can u please elaborate as i don't know what is dup2, i tried to search for a definition for the function in the man pages but what i got was not so descriptive

Reply With Quote
  #4  
Old June 9th, 2004, 04:01 PM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed God 2nd Plane (6000 - 6499 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 6,256 dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level) 
Time spent in forums: 2 Months 2 Weeks 5 Days 20 h 36 m 23 sec
Reputation Power: 1985
Quote:
Originally Posted by netbat
Can u please elaborate as i don't know what is dup2, i tried to search for a definition for the function in the man pages but what i got was not so descriptive

dup2 is just like dup with one important exception; from the man page:
Quote:
dup uses the lowest-numbered unused descriptor for the new descriptor.

dup2 makes newfd be the copy of oldfd, closing newfd first if necessary.

They both create a copy of the file descriptor, but dup choses the new file descriptor number for you whereas you can specify it explicitly with dup2. So dup2 gives you a bit more control over the process.

Reply With Quote
  #5  
Old June 9th, 2004, 05:14 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 94
^^what he said, pseudo code:

Code:
pipe(pipes)
if(fork == 0)
      dup2(pipe[WRITE], STDERR);
       close(pipe[WRITE]);
       exec(...)
else parent
       close(pipe[WRITE]);
       read(pipe[READ], ...); // this will be childs stderr stream

Reply With Quote
  #6  
Old June 9th, 2004, 07:56 PM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Let's start again here, what i know about process creation and exectution in unix is the forking concept and the exec functions, i know the general concept of piping but not how it is implemented in C, so go easy on me guys. Thanks

Reply With Quote
  #7  
Old June 9th, 2004, 08:14 PM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed God 2nd Plane (6000 - 6499 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 6,256 dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level) 
Time spent in forums: 2 Months 2 Weeks 5 Days 20 h 36 m 23 sec
Reputation Power: 1985
Quote:
Originally Posted by netbat
Let's start again here, what i know about process creation and exectution in unix is the forking concept and the exec functions, i know the general concept of piping but not how it is implemented in C, so go easy on me guys. Thanks :)

We are going easy on you. You should see what happens when we play rough! [grin]

Please bear with me, because I'm doing this from memory (not having actually done this for at least a year).

The pipe() call creates a pair of pipes in an array: one for reading and the other for writing.

When you fork, the child gets the open file descriptors of the parent, which the parent also still has.

The dup2(pipe[WRITE], STDERR); call by the child duplicates stderr to its write pipe (which is the read pipe for the parent). I'm not completely sure about closing the write pipe there; I thought that stderr had to have been closed first, but I'm sure that infamous is more up on this than I am and can explain that part -- personally I think that it should have been the child's read pipe that gets closed instead. Anyway, this sets it up so that whatever the program writes to stderr will instead get written out to the child's write pipe.

On the parent's side, he closes his own write pipe (the child's read pipe), because there is nothing he will want to send to the child. Then he reads his read pipe (the child's write pipe) for anything that got written to stderr.

Reply With Quote
  #8  
Old June 10th, 2004, 12:16 AM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 94
yup, in the child there should also be a close(pipes[READ]) as well, i forgots. the reason for closing the WRITE end also tho, is as follows:
dup2 will first close it's second argument, in this case STDERR. then it will re-open it, having it point to the file descriptor u pass as a first argument, the WRITE end of the pipe. at this point, u now have 2 references to the WRITE end of the pipe: 1)the fd returned by pipe, and 2)the reopened STDERR handle. on the other end, u have the parent waiting to read from the READ end of the pipe. that parent will keep reading until it receives an EOF. the problem is, u have 2 references to the same 'file', when STDERR is closed, that will leave 1 reference open still, and since there is still a reference, the parent will not be sent EOF until there are no refs left. now obviously in this particular situation, when the child exits all descriptors will be closed and EOF will be sent. but if u had different situation, say u had dup2'd two sockets for example, and u did not close the 2nd reference after the call to dup2, u can see the problem. so it's always good practice to close 2nd reference.

i'll try and expand on what dwise said a bit. on *nix, u have the concept "everything is a file". when u talk about STDOUT, STDIN, STDERR, these are all referenced thru file descriptors. when u open up a file with the open() system call, it returns to u a file descriptor, when u open up the serial port, it returns to u a file descriptor. the kernel views all these file descriptors as one and the same, a integer identifier used to reference a 'file' structure inside the kernel. each file descriptor is represented internally by a file structure. each process has a number of pointers to these file structures in its 'file table', a data structure maintained by the kernel. the number returned by open(), or the constants STDOUT_FILENO, etc, serve as an index into this table. when you call this:
Code:
dup2(fd1, fd2);

what happens is the pointer stored at index fd2 in the process's file table gets pointed at the same 'file' structure that the pointer at index fd1 is pointing to. so, now when u access fd2 u are accessing the same underlying file as fd1. so when a process does this:
Code:
dup2(some_fd, STDOUT_FILENO);

now everytime that process goes to write to STDOUT, it will actually be writing to some_Fd.

next thing u need to know is what pipe does. when u call:
Code:
int pipes[2];
pipe(pipes);

u create 2 new file descriptors, one for each array index. these 2 descriptors are tied to each other, when u write to the 2nd one, u can then read what u wrote on the first one. so:
Code:
write(pipe[1], "hi there"..);
read(pipe[0], buf, ..);
//buf will have 'hi there' in it

so u can see the use of pipes. as mentioned above by dwise, when a process forks a child, the child gets a copy of all the parents descriptors, ie a copy of the parents 'file table' i mentioned b4. if u create the pipes in the parent, they will then be available in the child as well, and what u write to write end of the pipe in the child will come out on the read end of the pipe in the parent(to be correct, it will also be readable thru the childs read end as well), and vice versa if u wanted to communicate other direction. u said u wanted the childs STDERR to be readable by the parent. so combine the 2 things i just talked about. what u want is the child to write its STDERR to the write end of the pipe, and for the parent to then read this output from the read end of the pipe. make sense?

note: if u really want to understand this stuff i suggest this book as i've left out some important stuff: http://www.kohala.com/start/apue.html

Last edited by infamous41md : June 10th, 2004 at 02:51 AM.

Reply With Quote
  #9  
Old June 10th, 2004, 05:35 AM
RevAntagonist RevAntagonist is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Location: South Africa
Posts: 5 RevAntagonist User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
Send a message via MSN to RevAntagonist
hey man ... i'd re-evaluate the if else statements b4 checking anything else...

Reply With Quote
  #10  
Old June 10th, 2004, 12:20 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 94
LOL thanks einstein, i think it's pretty clear that is labeled PSEUDO CODE, and that the indentation defines what belongs where...

Reply With Quote
  #11  
Old June 11th, 2004, 03:57 PM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
I think i got a grip of what u said guys, but now surfs two problems:
first, the dup2() accepts file descriptors, but STDERR is not a file descriptor, it's a _IO_FILE* or at least that's what gcc said.
now, i tried static cast : (int ) STDERR, but that trick didn't work

second, the read() function has the last argument to be the no. of bytes to read, and if set to zero it just returns zero and exits.

so?

thanks again and will really appreciate the reply

Reply With Quote
  #12  
Old June 11th, 2004, 04:01 PM
infamous41md's Avatar
infamous41md infamous41md is offline
not a fan of fascism (n00b)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Feb 2003
Location: ct
Posts: 2,756 infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level)infamous41md User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 2 Days 11 h 4 m 29 sec
Reputation Power: 94
the constants u want are STDOUT_FILENO , STDERR_FILENO, etc.. and im not sure what you're talkin about /w read().. u shouldn't be passing 0 or u wont read anything of course.

Reply With Quote
  #13  
Old June 11th, 2004, 05:03 PM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
thank u infamous, now it's working fine for the part of intercepting the STDERR, but i can't say print it my self
here is my code again:

PHP Code:
 int RunCommand(CommandTypecommand,bool mode
{
    
int pipes[2];
    
int pid;
    
int status;
    
int *buff = new int[1024];
    
    if(
mode == BACKGROUND)
        
pipe(pipes);
    
// creates child process
    
pid fork();
    
// checks for error
    
    
if (pid 0
    {
        
cout<<"Error in the fork process."<<endl;
        return 
1;
    }
    
    else if (
pid == 0
    {
        
//Child code
        
if(mode == BACKGROUND)
        {
            
dup2(pipes[0],STDERR_FILENO);
            
close(pipes[1]);
        }
        
int x execvp(command->namecommand->argv);
        if (
x<0
        {
        
cout<<PROMPT<<":"<<command->name<<": Command not found."<<endl;
        exit(
1);
        }
    }
    
    else 
    {
        if(
mode == FOREGROUND
        {
            
// Parent waits
            
while (wait(&status) != pid);
            return 
status;
        }
        else if(
mode == BACKGROUND)
        {
            
close(pipes[0]);
            
read(pipes[1],buff,1024);
            
cout<<*buff<<endl;
            
cout<<"Process ID for application "<<command->name<<": "<<pid<<endl;
            
cout<<"To terminate the application Type: kill "<<pid<<endl;
        }
        
    }
    return 
0;



and here is a sample output:

[nash - /home/ahmed/Desktop/Project]>kwrite &
0
Process ID for application kwrite: 5174
To terminate the application Type: kill 5174
[nash - /home/ahmed/Desktop/Project]>exit
Nada and Ahmed SHell, Terminating ...
[root@localhost Project]#


now see that zero b4 my usual output?? that is supposed to be what's in the buff variable, so??

Reply With Quote
  #14  
Old June 11th, 2004, 05:38 PM
NetBSD NetBSD is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Apr 2004
Location: Canada
Posts: 242 NetBSD User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 11 h 3 m 17 sec
Reputation Power: 0
Send a message via MSN to NetBSD
You're reading and writing from the wrong pipe descriptor. pipe[0] is for reading, pipe[1] is for writing.

Reply With Quote
  #15  
Old June 11th, 2004, 05:51 PM
netbat netbat is offline
Registered User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jun 2004
Posts: 8 netbat User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
i finally did it :)

Thanks a million guys both of you, i finally did it, the problem with the last code was some mixing between the pipes[0] and the pipes[1]

i mixed which was the read and which was the write end, also i had declared the buff as int which was out off haste, hehe.

but now it works superbly, thanks again, i owe u two one, so anytime anyone of u need anything msg me and i'll do my best, and that's a word of honor

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > fork() [intercept child process err to stdout]

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


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

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap