0

Original post:

I have been learning network programming from Beej's Guide to Network Programming for school. I'm currently working on a prototype for myself to communicate among multiple connections concurrently by using threads and I/O multiplexing. I'm getting a problem where when I receive a connection and call accept() to return a new file descriptor to "new_fd" instead of returning a new file descriptor it returns 1. This doesn't make sense to me because I'm not closing stdout anywhere in my code and accept() is supposed to return a reference to the socket as a new file descriptor, and as far as I know threads share the same file descriptors across a single process so it shouldn't be a problem that I have it threaded. I thought that the problem might be that I was connecting from my own computer using the loopback, but when I connected by referencing my ip address or another computer it also resulted in the same error of returning a fd of 1. I have no idea where to look anymore to solve this issue

Original posted code: http://pastebin.com/APQYjxg9 (I had posted all of my code)

Editing this for clarity. There were two things wrong with my code. The first one was pointed out by R.. immediately and that code snippet is here:

if (value = pthread_create((chat+chat_count), NULL, chatDaemon, (void *) &new_fd) != 0) 
{ -snip- }

void * chatDaemon(void * fd) 
{
    int my_fd = *((int *)fd);
    -snip-
}

I later figured out what went wrong and posted my answer. Code snippet for that here:

if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1) { -snip-}
Gallanoth
  • 91
  • 6

2 Answers2

2

Revisiting this after far too long. The lack of synchronization that R.. pointed out would have been a problem for this, however it was not causing the problem that I was experiencing. It was simply a small syntactical error with the accept logic so I originally had

if (new_fd = accept(listen_fd, (struct sockaddr*) &(remoteHost), &addrlen) != -1)

which as written evaluates and returns the result of the boolean check on accept to new_fd, which was always returning 1 for true. I did not realize at the time that c would order the operations that way and I fixed it with parentheses.

if ((new_fd = accept(listen_fd, (struct sockaddr*) &remoteHost), &addrelen)) != -1)
Gallanoth
  • 91
  • 6
1

Your problem seems to be a lack of synchronization reading *(int *)fd in chatDaemon. fd is a pointer to the local variable new_fd in main, which could be modified before or while chatDaemon is reading it, invoking undefined behavior. You either need to allocate storage for the int to store the fd and have chatDaemon free it, or (preferable) just cast it to void * and back rather than trying to pass the fd by reference.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • I'm pretty sure the standard doesn't guarantee that sizeof(void*) >= sizeof(int) so that'd be undefined too – Voo Nov 07 '14 at 06:36
  • @Voo: No, just implementation-defined. There are tricks to make it fully portable if you prefer, at some cost. – R.. GitHub STOP HELPING ICE Nov 07 '14 at 14:10
  • Since an implementation where an integer is larger than a pointer are theoretically possible I think, how would you do that? Interesting question. – Voo Nov 07 '14 at 17:58
  • @Voo: It's largely an academic question because such implementations don't exist, and even if they did, you'd have much bigger problems if file descriptor numbers could be that large. – R.. GitHub STOP HELPING ICE Nov 07 '14 at 20:34