Send () is always interrupted by EPIPE

I have this strange behavior on a multi-threaded server programmed in C under GNU / Linux. Although it sends data, SIGPIPE will eventually be interrupted. I managed to ignore the signals in send () and handle errno after each action because of this.

Thus, it has two separate sending methods: one that sends a large amount of data at the same time (or at least tries), and the other that sends almost the same amount and cuts it into small pieces. Finally, I tried to save data with this.

do
{
    total_bytes_sent += send(client_sd, output_buf + total_bytes_sent,
                             output_buf_len - total_bytes_sent, MSG_NOSIGNAL);
}
while ((total_bytes_sent < output_buf_len) && (errno != EPIPE));

This ugly piece of code does its job in certain situations, but not always.

I am sure that this is not a problem with the equipment or ISP, as this server runs on six European servers, four in Germany and two in France.

Any ideas?

Thanks in advance.

EDIT 1: yes, I noticed that this piece of code is crappy (thanks Jay). Initially, I meant that this code gives me EPIPE whenever the client disconnects or not.

EDIT 2: I tried using single send () and it gives me the same error randomly. This is strange because I cannot send a large chunk of data. I tried to increase the send buffer, but did not work.

EDIT 3: As requested, this is most of the code.

data_buf_len = cur_stream->iframe_offset[cur_stream->iframe_num - 1] - first_offset;
data_buf = cur_stream->data;
output_buf = compose_reply(send_params, data_buf, data_buf_len, &output_buf_len);

/* Obviously, time measuring is *highly* unaccurate, only for
 * design consistency purposes (it should return something).
 * */
clock_gettime(CLOCK_REALTIME, &start_time);
total_bytes_sent = send(client_sd, output_buf, output_buf_len, MSG_NOSIGNAL);
clock_gettime(CLOCK_REALTIME, &stop_time);
spent_time = (((int64_t)stop_time.tv_sec * NANOSEC_IN_SEC) +
    (int64_t)stop_time.tv_nsec) - (((int64_t)start_time.tv_sec * NANOSEC_IN_SEC) +
    (int64_t)start_time.tv_nsec);

free(output_buf);
unload_video(cur_video);

if (total_bytes_sent < 0)
{
    log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, cur_video->path);
    log_message(MESSAGE, __func__, IMSG_VIDEOSTOP, NULL);   
}

/* Hope it will not serve >2147483647 seconds (~68 years) of video... */
return ((int)spent_time);

Only one send () call with a large buffer. There is another example, too large to add here, which divides each buffer into smaller pieces and calls send () for each of them.

+3
3

EJP, EPIPE , . , , "total_bytes_sent" , send -1 , (: , errno EAGAIN, ).

, send 0, errno EPIPE, , .

EDIT: , shutdown . .

+4

, , . .

+1

, . SOCK_STREAM, .

, output_buf, .

send(client_sd, output_buf, output_buf_len, MSG_NOSIGNAL);

, select, , , -1, Jay.

Nos:

POSIX:

-

ssize_t send (int socket, const void * buffer, size_t length, int flags);

...

, O_NONBLOCK, send() , . , O_NONBLOCK, send() . select() poll() , , .

...

, , .

, , , . W. Richard Stevens libunp .

0
source

Source: https://habr.com/ru/post/1740281/


All Articles