Process fork
January 6th, 2009
I have to write an application for executing a process on a remote machine, and returnong the process stream data back to client. The problem i am having is that when the process name for execution ex "man" is sent to the server for execution the server receives the process name then hangs and the client keeps waiting for the stream data i.e stdout and stderr of the process
client
#include
#include
#include
#include
#include
#define TRUE 1
int main(int argc,char **argv){
int sock;
struct sockaddr_in server;
struct hostent *hp, *gethostbyname();
char buf[1024];
int readstatus;
/* Create socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
/* Connect socket using name specified by command line. */
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp == 0) {
fprintf(stderr, "%s: unknown host0", argv[1]);
exit(2);
}
bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
server.sin_port = htons(atoi(argv[2]));
if (connect(sock, &server, sizeof(server)) < 0) {
perror("connecting stream socket");
exit(1);
}
if (write(sock, argv[3], sizeof(argv[3])) < 0)
perror("writing on stream socket");
readstatus = read(sock,buf,100);
if(buf[0] == 'o') {
while(readstatus = read(sock,buf,100)) {
write(1,buf,sizeof(buf));
bzero(buf, sizeof(buf));
}
}
readstatus = read(sock,buf,100);
if(buf[0] == 'e') {
while(readstatus = read(sock,buf,100)) {
write(2,buf,sizeof(buf));
bzero(buf, sizeof(buf));
}
}
close(sock);
}
server
#include
#include
#include
#include
#include
#define TRUE 1
#define BUFSIZE 100
char buffer[BUFSIZE];
char buffer_err[BUFSIZE];
int main(int argc,char **argv) {
#include
int sock, length;
struct sockaddr_in server;
int msgsock;
char buf[1024];
int rval;
int i;
int stdin_pipe[2];
int stdout_pipe[2];
int stderr_pipe[2];
int readstatus;
int pid;
buffer[0] = 'o';
buffer_err[0] = 'e';
/* Create socket from which to read. */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
/* Name socket using wildcards */
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = 2603;
if (bind(sock, &server, sizeof(server))) {
perror("binding stream socket");
exit(1);
}
/* Find out assigned port number and print it out */
length = sizeof(server);
if (getsockname(sock, &server, &length)) {
perror("getting socket name");
exit(1);
}
printf("Socket has port #%dn", ntohs(server.sin_port));
/* Start accepting connections */
listen(sock, 5);
do {
msgsock = accept(sock, 0, 0);
if (msgsock == -1)
perror("accept");
while (rval = read(msgsock, buf, 1024)) {
printf("-->%sn", buf);
bzero(buf, sizeof(buf));
}
printf("received process to be executedn");
printf("executing process ......");
break;
} while (TRUE);
if(pipe(stdin_pipe) == 0 && pipe(stdout_pipe) == 0 && pipe(stderr_pipe) == 0) { //creating the pipes
pid = fork();
if(pid == -1) {
error("fork failure");
}
if(pid == 0) { // child process which will execute a new process and return stdio,stdin and stderr to client
close(0);
dup(stdin_pipe[0]);
close(stdin_pipe[1]);
close(stdin_pipe[0]);
close(1);
dup(stdout_pipe[1]);
close(stdout_pipe[0]);
close(stdout_pipe[1]);
close(2);
dup(stderr_pipe[1]);
close(stderr_pipe[0]);
close(stderr_pipe[1]);
execlp(buf,buf,"printf",NULL);
}
else { //we are in the parent process
close(stdin_pipe[0]);
close(stdin_pipe[1]);
close(stdout_pipe[1]);
close(stderr_pipe[1]);
while(readstatus = read(stdout_pipe[0],buffer,BUFSIZE)) {
write(msgsock,buffer,BUFSIZE);
bzero(buffer, sizeof(buf));
}
close(stdout_pipe[0]);
while(readstatus = read(stderr_pipe[0],buffer_err,BUFSIZE)) {
write(msgsock,buffer_err,BUFSIZE);
bzero(buffer_err, sizeof(buf));
}
close(stderr_pipe[0]);
}
close(msgsock);
close(sock);
}
return 0;
}
i am unable to detect the error , i think its is due to the child process creation please let me know the right solution.
regards,
Sheldon
all... But, let's start off with the fact that curses-type apps like "man" generally
aren't going to be happy just running with a pipe for stdout/stderr (and, a closed
stdin, in your case)... Usually, you have to run stuff like that in a pseudo-tty, in
order to make them work properly... You might want to try a simpler non-curses
app, like "cat" or "echo" or something, at least to start with, until you have the
other stuff working, at least...
In a great many places, you use sizeof(), when you really shouldn't... For instance:
if (write(sock, argv[3], sizeof(argv[3])) < 0)
You probably really wanted "strlen(argv[3])" there... sizeof() is likely to always
return 4 (or whatever the native pointer size is on your machine)...
while(readstatus = read(sock,buf,100)) {
write(1,buf,sizeof(buf));
bzero(buf, sizeof(buf));
}
For the write(), you should use "readstatus" as the length, not the entire sizeof(buf),
since most of it is guaranteed to be unfilled with any meaningful data (since it's
size is 1024, but you only read upto 100 bytes at most into it)! The return value
from read() will give you how much was read, and hence how much you should
write() to stdout... And, that bzero() isn't really needed for anything... Also, your
while() loop will only terminate on a return value of 0 from read(), which indicates
normal closure of the socket, but you probably also want to terminate on negative
return value (indicating error), as well... (Plus, you don't do anything outside the
loop to check for either error or EOF conditions, and so you'll just end up plowing
onward into the next loop...) These same basic problems apply in multiple locations
throughout the client and server code...
Your client expects the stdout data to be proceeded by a simple "o" message, and
the stderr by an "e", yet the server doesn't send any such thing... It puts those
chars at the start of its buffers, but then immediately overwrites them with the data
from the pipes...
And, immediately after accept()'ing a client, the server code does this:
while (rval = read(msgsock, buf, 1024)) {
printf("-->%sn", buf);
bzero(buf, sizeof(buf));
}
printf("received process to be executedn");
printf("executing process ......");
break;
Which means it won't reach that "break" (and move on to running the command)
until the client actually closes its end of the connection (so that you break out of
that while(read()) loop), by which time it's too late to send any data back to the
client...
There are probably even more problems, but that's about all I can handle tackling
at the moment...
#If you have any other info about this subject , Please add it free.# |