0

I have my server sending a large file to client(web browser) but when i refresh my page i am getting the conection reset by peer error and the program terminates. What i am expecting is server get a new connectiont.

 while (true)
    {
        check((new_socket = accept(server_fd, (struct sockaddr *)&address,

                                   (socklen_t *)&addrlen)),
              "accept_failed");
        read(new_socket, buffer_recv, 1024);
        printf("%s\n", buffer_recv);
        T = std::thread(handle_connection, new_socket);
        T.detach();
    }

handle_connection contains

while (file.read(&buffer[0], 1024))
    {
        s = file.gcount();
        content = chunk::make_chunk(buffer, s);
        check(write(new_socket, &content[0], content.size()), "Write_error");
    }

where check being simple error handling function and make_chunk return string.How can i make the server from not exiting and continue listening for connection please answer i am new to socket programming

Arjun U S
  • 199
  • 10
  • If this is the sum total of the code on your "web server", then something is definitely missing -- it appears to be that the shown code does not actually implement any part of HTTP. It's either that, or the shown code fails to meet the requirements of a [mre], as explained in the [help], and because of that it won't be possible for anyone to help you. – Sam Varshavchik Jun 19 '20 at 21:38
  • 2
    On Linux SIGPIPE signal can be generated when writing to a socket in certain scenarios causing the application to terminate by default. You can try `send(new_socket, &content[0], content.size(), MSG_NOSIGNAL);` instead of `write` to maybe get the error code instead of the signal. – dewaffled Jun 19 '20 at 21:45
  • 1
    Alternatively, you can use `setsockopt(SO_NOSIGPIPE)` on the new socket, then you can continue using `read()` and `write()`, and not have to specify `MSG_NOSIGNAL` on every `recv()` and `send()`. See [How to prevent SIGPIPEs (or handle them properly)](https://stackoverflow.com/questions/108183/). – Remy Lebeau Jun 19 '20 at 23:09
  • @RemyLebeau MSG_NOSIGNAL worked thank you . is there a way to terminate the thread rather than killing the whole process. – Arjun U S Jun 20 '20 at 10:01
  • 1
    @ArjunUS that is the whole point of disabling SIGPIPE. That will cause socket I/O operations to just fail with error codes that you can handle normally in your code, like breaking loops and exiting thread procedures, rather than killing your process. – Remy Lebeau Jun 20 '20 at 17:20

1 Answers1

1

Yes, you can use send() with MSG_NOSIGNAL or you can set SO_NOSIGPIPE socket option with setsockopt(). But with the minimal change in the existing code and for applying the settings to all the created sockets, You can do something like this:

From the man page of write()

EPIPE : fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will also receive a SIGPIPE signal. (Thus, the write return value is seen only if the program catches, blocks or ignores this signal.)

#include <signal.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>

int main()
{
    /* .... */

    sigset_t sigmask;

    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGPIPE);

    if (sigprocmask(SIG_BLOCK, &sigmask, NULL) != 0)  // get EPIPE instead
        goto handle_sigprocmask_fail;

    /* .... */

    int wr_return = write(sockfd, buf, sizeof(buf));

    if (wr_return == -1) {
        if (errno == EPIPE)
            goto handle_epipe;
    }
}
m0hithreddy
  • 1,752
  • 1
  • 10
  • 17
  • thank you Mohith MSG_NOSIGNAL worked for me. how can i terminate the current thread rather than killing the whole process when this signal happens – Arjun U S Jun 20 '20 at 09:59
  • @ArjunUS What is the need now, you wont be getting the SIGPIPE anymore. – m0hithreddy Jun 20 '20 at 10:04
  • From ``signal`` man page : A signal may be process-directed or thread-directed. A process-directed signal is one that is targeted at (and thus pending for) the process as a whole. A signal may be process-directed because it was generated by the kernel for reasons other than a hardware exception, or because it was sent using kill(2) or sigqueue(3). >> – m0hithreddy Jun 20 '20 at 10:11
  • A thread-directed signal is one that is targeted at a specific thread. A signal may be thread-directed because it was generated as a consequence of executing a specific machine-language instruction that triggered a hardware exception (e.g., SIGSEGV for an invalid memory access, or SIGFPE for a math error), or because it was targeted at a specific thread using interfaces such as tgkill(2) or pthread_kill(3). – m0hithreddy Jun 20 '20 at 10:11
  • I don't have clear picture about signal, My doubt is whether the send function keeps on writing to socket even after we close the client should we handle that case – Arjun U S Jun 20 '20 at 10:12
  • 1
    @ArjunUS Sounds like ``SIGPIPE`` is process directed, so it is placed in the process signal queue instead of thread signal queue, therefore we dont know which thread is responsible for generating ``SIGPIPE`` – m0hithreddy Jun 20 '20 at 10:14
  • 1
    @ArjunUS The harsh truth is yes, you need to handle that case, Refer to this link [why write() generates SIGPIPE instead of just giving -1 when receiving end is closed](https://stackoverflow.com/questions/2216374/why-is-writing-a-closed-tcp-socket-worse-than-reading-one/2218360#2218360) – m0hithreddy Jun 20 '20 at 10:28