1

This is not any error in code, but to get an idea how to accomplish the following criteria. I have seen similar questions here and here, but did not get any particular way to do it.

Consider the following parts of code:

....

pthread_create(&Receiver,NULL,ReceiveFromServer,(void*)&ClientSoc);
sending =1;
while (sending)
{
     SHOW_PROMPT;
     gets(message);
     memcpy(Packet.data,message,MAX_DATA_LENGTH);
     if (SetCommand(&Packet,message) == CMD_EXT)
         sending = 0;
     send(ClientSoc,&Packet,PACKET_SIZE,0);
}
close(ClientSoc);
pthread_join(Receiver,NULL);
return 0;
....

And the ReceiveFromServer function:

void* ReceiveFromServer(void* ClientSoc)
{
    int receiving =1;
    int Status;
    strPacket Packet;
    while(receiving)
    {
        if(recv(*(int*)ClientSoc,&Packet,PACKET_SIZE,0)>0)
        {
            ParseReply(Packet);
            SHOW_PROMPT;
        }
        if(GET_COMMAND(Packet.Header) == CMD_EXT)
            receiving = 0;
    }
    return NULL;
}

Assume everything is declared or defined correctly.

So the thread terminates depending upon the received data from server, but the sender still loops as it do not know that the receiver is terminated. The sender only comes out of loop depending upon the user input (a particular word such as 'exit').
How to notify the parent that the thread is terminating?
I tried to make sending global and change it from inside the thread, but it didn't work.

Community
  • 1
  • 1
Dipto
  • 2,720
  • 2
  • 22
  • 42
  • @suufang, I mentioned that I saw that question, but that is not answering this situation. – Dipto Feb 13 '14 at 10:12
  • Post a complete example that demonstrates your problem. _Assume everything is declared or defined correctly_ - that assumption gets you in trouble 100% of times. – Maxim Egorushkin Feb 13 '14 at 12:53
  • I don't get this. If the receiver terminates depending on what it received from the sender, the sender should know in advance the receiver would terminate and therefore this sender could terminate itself after having sent the terminating data to the receiver, couldn't it? – alk Feb 13 '14 at 13:28
  • @alk, The receiver and sender here are from a client program. It receives and sends to a server program. so this sender do not know what this receiver will get, as that is sent by the server. – Dipto Feb 13 '14 at 13:33
  • Ahok, I see .. must have been a temporary brain lapse on my side. You might like to go for Martin's approch as per his answer below. – alk Feb 13 '14 at 14:23

3 Answers3

2

Close the socket in the 'ReceiveFromServer' thread when you get the CMD_EXT. The sending thread should get the message soon enough - the send() call will return with an error.

Martin James
  • 24,453
  • 3
  • 36
  • 60
1

In the main loop of the parent, replace:

   while (sending)

with:

   while (sending && pthread_kill(Receiver, 0) != ESRCH)

This will check the existence of the Receiver thread. See How do you query a pthread to see if it is still running? for more info.

Note, however, that How do I determine if a pthread is alive? emphasizes that you cannot do this for a detached thread. And http://man7.org/linux/man-pages/man3/pthread_kill.3.html states:

POSIX.1-2008 recommends that if an implementation detects the use of a thread ID after the end of its lifetime, pthread_kill() should return the error ESRCH. The glibc implementation returns this error in the cases where an invalid thread ID can be detected. But note also that POSIX says that an attempt to use a thread ID whose lifetime has ended produces undefined behavior, and an attempt to use an invalid thread ID in a call to pthread_kill() can, for example, cause a segmentation fault.

Closing the socket in the ReceiveFromServer thread when you get the CMD_EXT, would probably also work, as Are parallel calls to send/recv on the same socket valid? seems to indicate POSIX sockets are thread safe. But R. strongly recommends against it in Is closesocket thread safe?. And the RHEL5 Linux man 2 close states:

It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be re-used, there are some obscure race conditions that may cause unintended side effects.

When dealing with sockets, you have to be sure that there is no recv(2) still blocking on it on another thread, otherwise it might block forever, since no more messages will be sent via the socket. Be sure to use shutdown(2) to shut down all parts the connection before closing the socket.

Also, you'll probably also want to replace gets(message) with a non-blocking equivalent, to handle the case where the peer asynchronously sends a CMD_EXT while you are waiting for human input.

And of course you'll need to add socket error-handling, but that is beyond the scope of this question.

Community
  • 1
  • 1
Joseph Quinsey
  • 9,553
  • 10
  • 54
  • 77
0

Maybe you could try to use pthread_tryjoin_np (I never used it) in the parent loop to detect if the thread has finished. It is only available for linux as I understood.

nlko
  • 500
  • 1
  • 6
  • 9