Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Andrzejek on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Help with fork() function !!

Status
Not open for further replies.

fredwang4

Programmer
Nov 29, 2002
1
US
Hi,
I am new to Unix C programming. I am trying to write a simple multi-process server. The server get an numberic input from keyboard and start a new child process, the child process does nothing but sleep for a few seconds and then exit. The parent process return to accept more input without waiting for the child process to exit.

The problem that I have is that after I fork() for a couple of times, that is acceptting inputs from keyboard for two or three times, the parent process begins to create process automatically without user input.

Here is the code that I wrote.
#define MAX_PROCESS 5;

static int current_process_num=0;
void install_sig_handler();
void sig_handler(int sig);


int main() {
int seconds;
int i;
install_sig_handler();
printf("pid: %d--enter seconds ", getpid());
fflush(stdout);
for(;;) {
scanf("%d", &seconds);
if (current_process_num < MAX_PROCESS){
current_process_num++;
switch (fork()){

case -1:
fprintf(fp,&quot;ERROR! Can not spawn child process\n&quot;);
exit(1);
case 0:
for (i=0;i<seconds;i++){
sleep (1);
}
_exit(0);
default:
break;
}
}
else {//has reach the limit
printf(&quot;has reached the limit, please try again\n&quot;);
fflush(stdout);
}
}
return 0;
}




void install_sig_handler(){
struct sigaction sig_struct;
sig_struct.sa_handler=sig_handler;
sigemptyset(&sig_struct.sa_mask);
sig_struct.sa_flags=0;
if(sigaction(SIGCHLD, &sig_struct, NULL)!=0){
perror(&quot;error&quot;);
exit(1);
}
}

void sig_handler(int sig){
pid_t pid;
int status;
while ((pid=waitpid(-1, &status, WNOHANG))>0){
current_process_num--;
// printf(&quot;one child has exited, and the current process num is %d\n&quot;,current_process_num);
}
}



Thanks for your kindly help and have a nice weekend

Fred

 
You need to clean up your input buffer. There are several ways to do that, but the basic problem is that you're getting newline characters in the buffer and not clearing them. If you're actually using C++ and not C, the you can use cin.ignore() to clear up everything. If not, you'll need something like fgets().
 
hmm.. this is the problem with scanf.
anyway .. do the following ...


Code:
scanf (&quot;%d&quot;, &seconds);
fflush (stdin);

br: nagi
 
fflush only flush output streams. If you use fflush on input streams the behaviour is undefined. Mostly the fflush(stdin) will just be ignored.
 
hi quagsire .. that is not true. you can use it on any stream ...

and it has, in my relatively long programming experience, never produced a result anything untoward or unpredictable.

br: nagi
 
From the man pages :
int fflush (Stream)
...
Parameters

Stream Specifies the output stream


From borland c++ :
If the given stream has buffered output fflush writes the output for stream to the associated file.


It is only in Visual C++ that it is specified that it will clear the input buffer.


Clearing the input buffer is not ANSI C/C++ for fflush. Borland C++ and IBM xlC compilers ignore fflush for input streams.
 
Hi,

Because you are using buffered input anytime you press enter key an newline character is entered into the keyboard buffer, and later your server program uses this newline as the new input so you have to empty the keyboard's buffer.

You can do it in two ways:

1- use the fflush() function with stdin or 1 as the argument.

2- You can put this piece of code to manually empty the buffer:
Code:
while (getchar() != '\n')
          ;
 
Hello

Coming back to the original problem (fflush is for output).

I don't like scanf to read from the input, so I would suggest using fgets and sscanf.
The trick however is to look at the return-value of scanf or fgets because signals tend to interrupt system-calls, and thus acting like there was input.
&quot;if (scanf(...) != 0)&quot; or &quot;if (fgets(...) != NULL)&quot; should do the trick. In this case flushing wasn't necessary in my test.
 
Now it is clear the problem is signals interrupt system calls.

Many ways to work it out, to restart it after signal interruption, or use sigaction.sa_flags as SA_RESTART.

As for input/output buffering, I believe both can be buffered. Unless you specify it using setvbuf(.), the default input (or output) is line-buffered. However I don't think input buffer is of any help in scanf(.).

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top