2

considering being new to C language on Linux, I've walked through socket programing scenarios where you have to handle that SIGPIPE issues and I've faced the fllowing cases:
1- catch sigaction for the process then continue, which equals ignoring the signal.

struct sigaction sginal_action;
memset(&sginal_action, 0, sizeof (sginal_action));
sginal_action.sa_handler = SIG_IGN;
sginal_action.sa_flags = SA_RESTART;
if (sigaction(SIGPIPE, &sginal_action, null)) {
    perror("signal action error"); 
}

2- ignore the signal over thread using

sigset_t sigpipe_mask;
sigemptyset(&sigpipe_mask);
sigaddset(&sigpipe_mask, SIGPIPE);
sigset_t saved_mask;
if (pthread_sigmask(SA_RESTART, &sigpipe_mask, &saved_mask) == -1) {
  perror("pthread_sigmask");
}



-Now every thing shall work fine but I need an answer about this test case behavior:

1- server accepted socket from user A with file discriptor int 7
2- I run lengthy SQL statement that takes 25 secondes
3- at second 20 client closed socket
4- at second 21 Linux kernel sent SIGPIPE
5- at second 22 process ignored SIGPIPE and continued working with file decriptor 7, since there is no signal any thing went wrong
6- at second 23 server accepted socket from user B with file discriptor int 7, again!
7- user B authorization takes 2 seconds shall finish at second 25 of user A.
8- the core problem starts at second 25 write(file_dsciptor, buffer, buffer_size); from both threads will write data to both user A and user B channels
9- it happens that user B is not authorized to login to server but before server close file decriptor 7 at thread B, thread A of client A writes to file decriptor 7 and client B received vital data due to the reuse of socket file descriptor 7!

My question,
is that scenario wrong and will never happen?
or that is possible to happen but there is a correct method to apply?
and is there a C system call function to stop file_discriptor re-usage over socket connections?
or what shall be done to ensure that opened channel is not conflicted with another channel, like unique file discriptor I guess?

  • 2
    Step 6 should never happen. Until you `close` a file descriptor, it cannot be returned by a call to `socket` or `accept` since it's in use until it's closed no matter what happens to the connection. You must not `close` a file descriptor, no matter what errors you may or may not get related to it, until you are 100% confident no thread will attempt to use that descriptor to access the connection is refers to -- even if that connection has errored! – David Schwartz May 18 '18 at 21:16
  • *at second 22 process ignored SIGPIPE and continued working with file decriptor 7, since there is no signal any thing went wrong* While there may be no *signal* that something went wrong, there is most certainly the *return value* from the function calls you make on the file descriptor. See https://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly – Andrew Henle May 19 '18 at 13:08

1 Answers1

5

(Normal) SIGPIPE is essentially a synchronous signal. You get it in response to what you did which is attempt a write into a pipe/socket/FIFO that was closed by the other side. Ignoring SIGPIPE is quite harmless since if you do that, you'll still get informed about the error the usually way synchronous errors are reported: by a failing return code and errno set to the appropriate error number (EPIPE). In this case, I think ignoring SIGPIPE while continuing to check for errors would be the best way to proceed regardless of the POSIX platform you're on.

Concerning your example, your assumption at point 5 that there will be "no signal any thing went wrong" is incorrect. There will be a signal. It just won't be a signal but an EPIPE fail on a write call.

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142
  • FWIW, I've been programming for a few decades in C, and I don't think I've ever done anything with `SIGPIPE` but ignore it with `sigignore( SIGPIPE );` – Andrew Henle May 19 '18 at 13:06