Socket () returns 0 in the client server C application

I am working on an application containing several server sockets, each of which runs in a unique thread.
One of the threads is called by an external utility (script). This script calls a utility (client) that sends a message to one of the server sockets.

Initially, I used system() to execute this external script, but we could not use it because we needed to make sure that the server sockets were closed in a child element that was forked to execute the external script.
Now I call fork() and execvp() . I fork() and then in the child I close all server sockets and then call execvp() to execute the script.

Now it all works great. The problem is that at times the script reports errors to the server application. The script sends these errors, invoking another application (client) that opens the TCP socket and sends the corresponding data. My problem is that the client application gets the value 0 returned by the socket() system call.

NOTE. This ONLY happens when the script / client application is called using my forkExec () function. If the script / client application is called manually, the socket() call is executed appropriately and everything works fine.

Based on this information, I suspect it is something in the 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 Application 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

+6
linux arm fork sockets exec
source share
4 answers

socket () returns -1 on error.

A return of 0 means that socket () succeeded and gave you a file descriptor of 0. I suspect that one of the file descriptors that you close has a file descriptor of 0 and after closing it, the next call to the function that allocates the file descriptor will be return fd 0 as it is available.

+9
source share

A socket with a value of 0 is excellent, which means that stdin has been closed, which will make fd 0 reusable - for example, a socket.

Most likely, one of the filedescriptors that you close in the root path of forkExec () (XMLSocket / ServerFd), etc.) was fd 0. This will launch the child with the closed fd 0, which will not happen when you run the application from command line, since fd 0 will already be open as a stdin shell.

If you want your socket not to be 0,1 or 2 (stdin / out / err), call the following in your forkExec () function after all calls to close ()

 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); } 

Verify that the socket returns -1, which indicates an error has occurred.

+4
source share

Do not forget to call

 waitpid() 

The end of the "obvious question." I take a little here, but you are not doing anything with the pid returned by the fork () call. (-:

+1
source share

As mentioned in another comment, you really should not close 0.1 or 2 (stdin / out / err), you can put a check to make sure that you do not close it, and therefore it will not be assigned as new fd`s when you request a new socket

0
source share

All Articles