LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 07-27-2011, 08:26 PM   #1
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Rep: Reputation: 70
Questions about a C program...


I'm studying an OS programming book, in particular network sockets. I have two questions(2nd one is down at the bottom). There is something I don't quite understand. What if this piece of code, which sets sigpipe's default action to ignore and opens a socket:
Code:
if ((u_ignore_sigpipe() != 0) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))
   return -1;
is replaced by this
Code:
if  (((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) || (u_ignore_sigpipe() != 0) )
   return -1;
The books says that this problem would arise: "if u_ignore_sigpipe() fails, u_connect returns with an open file descriptor in sock. Since the calling program does not have the value of sock, this file descriptor could not be closed."

What I don't understand is that socket gets run first and returns a file descriptor to sock, then u_ignore_sigpipe() gets evaluated. So if u_ignore_sigpipe() fails then sock doesn't get assigned? It would make sense if in the if statement, order of precedence goes from right to left so that if u_ignore_sigpipe() fails, then the if statement would just break and socket() would not even run. Is this the case?

Here's the complete program
Code:
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "uiciname.h"
#include "uici.h"

int u_ignore_sigpipe(void);

int u_connect(u_port_t port, char *hostn) {
   int error;
   int retval;
   struct sockaddr_in server;
   int sock;
   fd_set sockset;

   if (name2addr(hostn,&(server.sin_addr.s_addr)) == -1) {
      errno = EINVAL;
      return -1;
   }
   server.sin_port = htons((short)port);
   server.sin_family = AF_INET;

   if ((u_ignore_sigpipe() == -1) ||
        ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))
      return -1;

   if (((retval =
       connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) &&
       ((errno == EINTR) || (errno == EALREADY))) {          /* asynchronous */
       FD_ZERO(&sockset);
       FD_SET(sock, &sockset);
       while (((retval = select(sock+1, NULL, &sockset, NULL, NULL)) == -1)
           && (errno == EINTR)) {
          FD_ZERO(&sockset);
          FD_SET(sock, &sockset);
       }
   }
   if (retval == -1) {
        error = errno;
        while ((close(sock) == -1) && (errno == EINTR));
        errno = error;
        return -1;
   }
   return sock;
}
I'm also confused about what happens if the connect() function fails with either EINTR or EALREADY. EINTR is just when the connect() function gets interrupted by a signal. EALREADY is when the connection request is already in progress on a socket. So if either one is true,

1. What does FD_ZERO(&sockset) and FD_SET(sock, &socket) do?
Do they zero out the file descriptor and then sets it back to value of sock?
2. Then it runs select(), what does that do exactly? The book only says that it calls select to detect that the file descriptor is ready for writing. So basically the TCP 3 way handshake is complete, and select() makes sure that the socket is open for write?
 
Old 07-27-2011, 08:50 PM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
For your first question, in the C programming language, when a conditional statement has something like (A || B), if A is true, then B is not evaluated. B will only be evaluated when A is false.

Thus for the following statement:
Code:
if  (((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) || (u_ignore_sigpipe() != 0) )
if the socket is created successfully, then the u_ignore_sigpipe() function will NOT be called. (EDIT: This statement is incorrect; u_ignore_sigpipe() will be called if the socket is created successfully).

For your other question concerning FD_ZERO(), FD_SET(), etc., these work on a file-descriptor set. The former zeroes out the set, and the latter adds the socket descriptor to the set. When calling select(), the highest socket descriptor plus one (1), should be passed as the first arg to the function.

select() can be used to tell you when it is appropriate to read from a socket, write to it, or handle an error. select() can be used to monitor multiple sockets at a time. Typically it is used for determining when it is ok to read, but I've seen it used for purposes of determining when it is ok to write. I've never seen it used for determining errors.

If you want to learn Socket Programming with an easier guide, I recommend Beej's documentation.

Last edited by dwhitney67; 07-28-2011 at 03:36 AM. Reason: Posted comment concerning incorrect statement made in original reply.
 
1 members found this post helpful.
Old 07-27-2011, 11:00 PM   #3
trist007
Senior Member
 
Registered: May 2008
Distribution: Slackware
Posts: 1,052

Original Poster
Rep: Reputation: 70
Great thank you dwhitney67.
 
Old 07-28-2011, 03:34 AM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by trist007 View Post
Great thank you dwhitney67.
You're welcome, however I provided you with false information... sorry... I really shouldn't post replies late at night.

With the following statement:
Code:
if  (((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) || (u_ignore_sigpipe() != 0) )
I did not pay close enough attention to the first conditional; if the socket is created successfully, then the return value from socket() will NOT be -1; thus that first conditional will be FALSE. This will force the second half of the conditional to be evaluated; in other words, u_ignore_sigpipe() will be called.

Sorry for the confusion; the comment I made earlier regarding (A || B) still apply, but my analysis of the statement above was off.

Once again, sorry for the confusion.
 
  


Reply



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

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
program questions tsunami_imcool Debian 1 09-12-2006 11:01 AM
Program questions $Linuxnoob Fedora 4 04-10-2006 01:34 AM
Kasablanca ftp program questions gizmobay Linux - Newbie 3 11-23-2005 10:06 AM
SLIP and Hyperterminal like program questions brassmon_k Linux - Networking 4 11-03-2001 01:37 PM
questions about installing a program on linux... Nightrain Linux - Software 5 07-17-2001 10:49 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration