-4

I created a thread with pthread_create() for the execution of a function, inside the function there is a write() function to send data via socket descriptor. If the write() function fails to send data (because the socket connection is lost), my thread is terminated.

Can I keep a thread when write() fails?

This is my code:

   void broadcastMsg(char *msg) {
        int i=0;
        while(1) {
            ...
            ...
            // My thread terminated from here
            if(write(client_database.sock_desc[i], msg, strlen(msg)) < 0) {
                client_database.sock_desc[i] = -3;
                i++;
                continue;
            }

            i++;
        }
    }

    /* Start thread from this function */
    void *cliListener(void *argvp) {
        int read_desc;
        char buf[MAX_TRANSFER_BUF];
        int cli_sock_desc_id = atoi(argvp);

        while(1) {
            memset(buf, 0, MAX_TRANSFER_BUF);
            read_desc = read(client_database.sock_desc[cli_sock_desc_id], buf, MAX_TRANSFER_BUF);

            ...
            ...

            broadcastMsg(buf);
        }
    }

    int main(void) {
        ...
        ...
        pthread_t tid_1;
        pthread_create(&tid_1, NULL, cliListener, cli_listener_arg);
        ...
        ...
    }
RamenChef
  • 5,557
  • 11
  • 31
  • 43
  • Yes, you can keep a thread after a failed write. To say more, such as why the thread terminated, we need to see the code. Please provide a minimal but complete example that still has the same problem. – Thomas Padron-McCarthy Dec 23 '17 at 20:05
  • Is [this previous question](https://stackoverflow.com/questions/42442387/is-write-safe-to-be-called-from-multiple-threads-simultaneously) useful? – Weather Vane Dec 23 '17 at 20:06
  • Without a simple example we cannot help you – doron Dec 23 '17 at 20:07
  • There is a button [edit] directly under your post (it's kinda small and grey but it's there). You can also click the link in this comment :) Make sure to create an [mcve]; also read [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask). You probably want to skim the [tour] at least once, as it covers the very basics. – Jongware Dec 23 '17 at 21:07

1 Answers1

2

If you try to write to a pipe or socket descriptor where the other end of the pipe or socket has been closed (so noone will ever read it), the system will send a SIGPIPE signal to your process, which by default will kill the process1. You can avoid this fate by ignoring SIGPIPE, generally early in the main function:

signal(SIGPIPE, SIG_IGN);

once you do this, the write will no longer kill your thread or process; instead it will return an error (-1) with errno set to EPIPE. You need to make sure you are ALWAYS checking the return value of your write calls, and doing the appropriate thing when there is an error, otherwise your program might run on in background after you think it has stopped...


1Depending on how you've set things up it might kill just the thread and not the entire process, but for general safety and hygiene its supposed to kill the entire process

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • I see my code a few hours for this, and this is solved by adding signal(SIGPIPE, SIG_IGN); on main(). Thanks for this solution, it's hard to be a newbie :D – Septian Dwi Cahya Dec 23 '17 at 20:39
  • I want to emphasize ALWAYS checking `write` return values if you're ignoring SIGPIPE. Its very easy to get programs that hang around after you think you've killed them, eating up resources otherwise. Note that that includes all library functions that use `write` under the hood (such as `printf`). – Chris Dodd Dec 23 '17 at 20:42