This worked flawlessly in node 0.6.19 but now fails.
I wrote a forking UDP server in node. However, node doesn't have a real fork and cluster doesn't do UDP, so I wrote a module in C++ that simply calls fork (the module that contains this function is called "hasher")
static Handle<Value> spoon(const Arguments& args) // node sees this function as "fork"
{
HandleScope scope;
pid_t rval = fork();
if (rval < 0)
{
return ThrowException(Exception::Error(String::New("Unable to fork daemon, pid < 0.")));
}
Handle<Value> n = v8::Number::New(rval);
return n;
}
I bind the UDP port, and fork all the children.
udp_server.bind(argv.udp_listen_port, '0.0.0.0');
// now create multiple children (loop starting with 1 is on purpose)
for (var i = 1; i < argv.multiple; i++)
{
var pid = hasher.fork();
if (pid == 0)
break;
}
Theoretically, the child processes should not know that someone else is sharing that port and should behave normally. However, I almost immediately (1 or 2 incoming UDP packets) trigger an assert message:
node-0.10.29: ../deps/uv/src/unix/stream.c:499: uv__server_io: Assertion `events == 1'
failed.
Aborted (core dumped)
Anyone have a clue as to what is going on?
Related
I'm currently learning how to use system calls such as fork, exec*, and kill. I had a task that required to send SIGKILL to all parent's sibilngs created with fork if one of fork calls failed. So I did smth like this:
for (int i = 0; i < numOfchilds; i++) {
childs[i] = fork();
if (childs[i] == -1)
killAll(childs, i);
...
void killAll(pid_t childs, size_t numOfChilds) {
for (int i = 0; i < numOfChilds; i++)
kill(childs[i], SIGKILL);
}
But I messed up and accidentally send kill(-1, SIGKILL) and killed all processe that I could. Fortunately I didn't lose any unsave data, but kill -9 -1 is not the best practice to logout.
So. Is there any way I can restrict my program killing any processes that don't belong to it, so it could only kill one it created with fork?
I have this code:
server
while(1){ //loop the child
bzero(buffer, 256);
n = recv(newsockfd, buffer, 255,0);
printf("read %d ",n);
printf("pid %d\n",getpid());
if (n < 0) error("ERROR reading from socket");{
printf("Here is the message: %s\n", buffer);
}
if (strcmp(buffer,"quit") == 0){
printf("Disconnect from %s:%d\n",str,portno);
exit(EXIT_SUCCESS);
}else{
n = send(newsockfd, "message received\n", 19,0);
if (n < 0) error("ERROR writing to socket");
bzero(buffer, 256);
}
}
}else{ //parent
recv(newsockfd,gepid,10,0); //get the child pid
endID = waitpid(gepid,&status,WNOHANG|WUNTRACED); //get the exit code gepid want to be the child pid
if (endID==-1){
error("waitpid");
}else if (endID==0){
printf("Child still running!");
}else if(endID==childpid){
check_child_exit(status);
}
}
}
close(newsockfd);
return 0;
}
client
while(1){ //while after connect
printf(inet_ntoa(serv_addr.sin_addr));
printf(" :>");
bzero(buffer, 256);
printf("pid: %d",&getpid);
//fgets(buffer,255,stdin);
scanf("%s",&buffer[0]);
if ( send(sockfd, buffer, strlen(buffer),0)< 0)
error("ERROR writing to socket");
if(strcmp(buffer,"quit") == 0){
close(sockfd);
printf("Client: %s Disconnect \n",inet_ntoa(serv_addr.sin_addr));
gepid[0]=getpid(); //there is the error i want to get the pid of child
send(sockfd,gepid,10,0); //and send to server
exit(1);
}
if (recv(sockfd, buffer, 255,0)< 0){
error("ERROR reading from socket");
}else{
printf("%s\n %d", buffer,n);
}
}
return 0;
}
I have a server that can serve multy client and response to each one when the client write quit or stop with a signal[CTR-C] i want the server get that and avoid zombie proccess so to avoid zombie proccess i thought
to send from client to server the getpid so the client get the pid of the kid proccess when the proccess finish with quit or stop by signal parent get the exit with waitpaid
so the programm not have zombie proccess i dont know if this logic is good to stop the zombie proccess but i try to send pid from client to server and i get segmentation fault
Any help is appreciate
There are numerous problems with your code, but to focus on your question:
Don't try sending the pid to the server. It's unnecessary, and wouldn't work if the child crashes before it can send it anyway.
The usual way is to catch the SIGCHLD signal, and do any necessary waitpid stuff from inside the signal handler. But if your only concern is avoiding zombies, then just install a default signal handler with signal(SIGCHLD, SIG_IGN);, and don't use waitpid at all.
fork() returns 0 in the child and the child pid in the parent, so there is no need to send pid from child to parent. If you are forking multiple times, then you need to store each child pid for collection later.
You are not showing the type of gepid. Is it pid_t gepid2 or something? The len parameter to recv() is in bytes, so it would be more appropriate to recv(sock, gepid, sizeof(gepid[0]), 0);
Also if you pass -1 to waitpid(), it waits for any child.
I am creating a shell command from the custom shell to do the ssh from one terminal to another terminal.
In order to do the ssh, I am using the inbuilt ssh command of the linux. Here is my code that does the ssh login.
However, I am seeing that the I/O buffers are not in sync.
This is what I am seeing on the terminal. After SSH to the other terminal. I did the following in the terminal.
PRT# ssh 192.168.10.42
PRT# Could not create directory '/root/.ssh'.
root#192.168.10.42's password:
# screen -r
-sh: cen-: not found
# hello
-sh: el: not found
#
I don't what's the reason here. Here is the code.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
}
return 0;
}
Based on Patrick Ideas.
POST 2# - It seems that it works when we close the stdin in the parent process. However, it becomes very slugguish, I feel like I am typing the keyboard too slow. The system becomes too sluggish. Also, I have a web-server from this terminal. I see that I can no longer access the web.
So, the solution is somewhere around stdin but I am not sure.
int sshLogin(chr *destIp)
{
char cmd[CMD_LEN];
char readbuff[CMD_LEN];
pid_t pid;
int ret = 0;
int fd[2];
int result;
memset(cmd,'\0',sizeof(cmd));
int status = 0;
/** --tt required to force pseudowire allocation because we are behind screen app **/
sprintf(cmd,"/usr/bin/ssh -tt %s",destIp);
/** create a pipe this will be shared on fork() **/
pipe(fd);
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0 )
{
/** Child Process of Main APP --Make this parent process for the command**/
if((pid = fork()) == -1)
{
perror("fork:");
return -1;
}
if( pid == 0)
{
/** basically Main APP grand child - this is where we running the command **/
ret = execlp("ssh", "ssh", "-tt", destIp, NULL);
printf("done execlp\r\n");
}
else
{
/** child of Main APP -- keep this blocked until the Main APP grand child is done with the job **/
while( (read(fd[0], readbuff, sizeof(readbuff))))
{
printf("%s",readbuff);
}
waitpid(0,&status,0);
LOG_STRING("SSH CONNC CLOSED");
exit(0);
}
}
else
{
/** Parent process APP MAIN-- **/
/** no need to wait let APP MAIN run -- **/
close(stdin);
}
return 0;
}
Basically, I have added - close(stdin);
You have 2 different processes trying to read from STDIN. This causes process 1 to get char 1, process 2 to get char 2, process 1 to get char 3, process 2 to get char 4, etc, alternating back and forth.
Your 2 processes are:
execlp("ssh", "ssh", "-tt", destIp, NULL);.
while( (read(fd[0], readbuff, sizeof(readbuff))))
Basically you need to ditch the read(fd[0],...).
My initial thought is that perhaps it is buffering the output: stdout is buffered, so unless you print a newline, nothing will be printed until a certain number of characters build up. This is because I/O operations are expensive. You can find more detail on this here. The result is that there is a delay because your program is waiting to print.
My suggestion: in your main function, before calling your sshLogin function, try disabling buffering with this line of code:
setbuf(stdout, NULL);
You can also call fflush(stdout); periodically to do the same thing, but the above method is more efficient. Try it and see if that solves your problem.
I am doing an assignment using pthreads and mutual exclusion. I have to create n print servers and m print clients, who each have 5 print jobs. We are to create the threads, pass the jobs through a queue of size 4 to the print servers which then print the job (ie busy work in this case). Here is the code for passing the jobs and servicing the jobs.
These are the client and server threads
void *PrintClient(void *arg){
int i;
char str[NUMJOBSPERCLIENT][100];
for(i=1;i<NUMJOBSPERCLIENT;i++){
pthread_mutex_lock(&mutex);
req.clientID = pthread_self();
req.fileSize = rand_int(FILEMIN,FILEMAX);
sprintf(str[i], "File_%d_%d",pthread_self(),i);
req.fileName = str[i];
append(req);
pthread_mutex_unlock(&mutex);
sleep(rand_int(1,3));
}//for
pthread_exit(NULL);
} // end PrintClient
void *PrintServer(void *arg){
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
while(count > 0){
take();
count = count -1;
}
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
} // end PrintServer
And this is code which adds or removes a job from the queue. I know the error is here and it had to do with the threads themselves but I can not find it for the life of me. So far the debugger has been almost no help (I am running on a university linux server which is showing no compile errors).
void append(PrintRequest item){
BoundBuffer[count] = req;
printf("I am client %s\n",req.fileName);
count++;
if(count == BUFSIZE){
printf("Buffer Size Reached\n");
pthread_cond_signal(&cond);
}
} // end append
PrintRequest take(){
printf("Printing %s\n", BoundBuffer[count].fileName);
usleep(BoundBuffer[count].fileSize/PRINTSPEED);
printf("Finished Printing %s\n", BoundBuffer[count].fileName);
} // end take
I guess the segmentation fault is signaled around printf("Printing %s\n", BoundBuffer[count].fileName);, right?
In your PrintClient, you store file name to local variable str[][] and copy the pointer to this local variable as one parameter of the request req.fileName = str[i];. Thus the address pointed by req.fileName is allocated on the stack of the client thread.
When the requests are processed in the server thread PrintServer, it is possible that the client thread which generated the request is no longer present. The result is that req.fileName points to an address which doesn't exists (the stack memory has already been de-allocated with the exiting of the client thread), then when you de-reference such address in printf("Printing %s\n", BoundBuffer[count].fileName);, segmentation fault is signaled.
I'm working on an application that contains several server sockets that each run in a unique thread.
An external utility (script) is called by one of the threads. This script calls a utility (client) that sends a message to one of the server sockets.
Initially, I was using system() to execute this external script, but we couldn't use that because we had to make sure the server sockets were closed in the child that was forked to execute the external script.
I now call fork() and execvp() myself. I fork() and then in the child I close all the server sockets and then call execvp() to execute the script.
Now, all of that works fine. The problem is that at times the script reports errors to the server app. The script sends these errors by calling another application (client) which opens a TCP socket and sends the appropriate data. My issue is that the client app gets a value of 0 returned by the socket() system call.
NOTE: This ONLY occurs when the script/client app is called using my forkExec() function. If the script/client app is called manually the socket() call performs appropriately and things work fine.
Based on that information I suspect it's something in my fork() execvp() code below... Any ideas?
void forkExec()
{
int stat;
stat = fork();
if (stat < 0)
{
printf("Error forking child: %s", strerror(errno));
}
else if (stat == 0)
{
char *progArgs[3];
/*
* First, close the file descriptors that the child
* shouldn't keep open
*/
close(ServerFd);
close(XMLSocket);
close(ClientFd);
close(EventSocket);
close(monitorSocket);
/* build the arguments for script */
progArgs[0] = calloc(1, strlen("/path_to_script")+1);
strcpy(progArgs[0], "/path_to_script");
progArgs[1] = calloc(1, strlen(arg)+1);
strcpy(progArgs[1], arg);
progArgs[2] = NULL; /* Array of args must be NULL terminated for execvp() */
/* launch the script */
stat = execvp(progArgs[0], progArgs);
if (stat != 0)
{
printf("Error executing script: '%s' '%s' : %s", progArgs[0], progArgs[1], strerror(errno));
}
free(progArgs[0]);
free(progArgs[1]);
exit(0);
}
return;
}
Client app code:
static int connectToServer(void)
{
int socketFD = 0;
int status;
struct sockaddr_in address;
struct hostent* hostAddr = gethostbyname("localhost");
socketFD = socket(PF_INET, SOCK_STREAM, 0);
The above call returns 0.
if (socketFD < 0)
{
fprintf(stderr, "%s-%d: Failed to create socket: %s",
__func__, __LINE__, strerror(errno));
return (-1);
}
memset(&address, 0, sizeof(struct sockaddr));
address.sin_family = AF_INET;
memcpy(&(address.sin_addr.s_addr), hostAddr->h_addr, hostAddr->h_length);
address.sin_port = htons(POLLING_SERVER_PORT);
status = connect(socketFD, (struct sockaddr *)&address, sizeof(address));
if (status < 0)
{
if (errno != ECONNREFUSED)
{
fprintf(stderr, "%s-%d: Failed to connect to server socket: %s",
__func__, __LINE__, strerror(errno));
}
else
{
fprintf(stderr, "%s-%d: Server not yet available...%s",
__func__, __LINE__, strerror(errno));
close(socketFD);
socketFD = 0;
}
}
return socketFD;
}
FYI
OS: Linux
Arch: ARM32
Kernel: 2.6.26
socket() returns -1 on error.
A return of 0 means socket() succeeded and gave you file descriptor 0. I suspect that one of the file descriptors that you close has file descriptor 0 and once it's closed the next call to a function that allocated a file descriptor will return fd 0 as it's available.
A socket with value 0 is fine, it means stdin was closed which will make fd 0 available for reuse - such as by a socket.
chances are one of the filedescriptors you close in the forkExec() child path(XMLSocket/ServerFd) etc.) was fd 0 . That'll start the child with fd 0 closed, which won't happen when you run the app from a command line, as fd 0 will be already open as the stdin of the shell.
If you want your socket to not be 0,1 or 2 (stdin/out/err) call the following in your forkExec() function after all the close() calls
void reserve_tty()
{
int fd;
for(fd=0; fd < 3; fd++)
int nfd;
nfd = open("/dev/null", O_RDWR);
if(nfd<0) /* We're screwed. */
continue;
if(nfd==fd)
continue;
dup2(nfd, fd);
if(nfd > 2)
close(nfd);
}
Check for socket returning -1 which means an error occured.
Don't forget a call to
waitpid()
End of "obvious question mode". I'm assuming a bit here but you're not doing anything with the pid returned by the fork() call. (-:
As it is mentioned in another comment, you really should not close 0,1 or 2 (stdin/out/err), you can put a check to make sure you do not close those and so it will not be assigned as new fd`s when you request for a new socket