0

I am writing a custom HTTP server in C for my OpenWrt router. It makes use of the uclibc library. I am only using one static buffer which I am very careful not to overflow, and no multi-threading is involved. It doesn't contain any complex data structures, and what it does is that:

  • it listen() s on the socket
  • reads the request after accept() ing
  • gets an html page by sending an http request to a predefined remote server (not a proxy)
  • sends the result through the accepted connection, and closes both.

The program would just stop running after some time, (it can be on receiving the first request, or after working under heavy strain for more that 2 hours). I am getting no error messages through the console, or anything, the program just stops. I have watched it and, as expected it doesn't consume more and more memory as it runs...

  • Is it possible that the kernel stops it if it thinks its abusing the CPU? How do I overcome that?
  • Are there some quirks to watch for in socket programming in C that are known to cause such crashes?
  • Can the stability issues be caused by using the Barrier Bracker (bleeding edge) branch of OpenWrt? Although the router itself never stops working...

Where do I start to look for the source of the problem?

  • Attach a debugger to your process when it's hung, and look at what it's doing. – Mat May 18 '14 at 19:13
  • please show the code. – jfly May 19 '14 at 01:10
  • You mentioned that there is only a single thread. However, the normal method is to have a pool of threads and have the listen/accept sequence dispatch a thread from the pool to handle the individual request. How are you handling the 'backlog' when more than one request is waiting. Usually a following request overwrites (depends on the OS) the prior request, if it has not already been dispatched. – user3629249 May 20 '14 at 04:47
  • Mat, how would I attach a remote debugger on the router itself? jfly, I'll have to get a permission from a quite a few people to do that, sorry... @user3629249, I am developing a custom (we _have_ checked out the others) captive portal system, that *has* to show the "_log in to wifi_" notification. It doesn't get shown, if some other request (from a third party app) gets processed through the router before the captive portal detection request (this _does_ happen...). So I need to process a request at a time. Is it possible? I'm not sure I understand your last sentence. Thanks all. – user3650388 May 20 '14 at 13:25

2 Answers2

1

Ok, first, I would like to thank everybody for helping. After writing a lot of netcat testers, I have pinpointed the problem. The program would crash - end without a single error message, if the connection is closed by the client before the last write or read occurs. The write or read would raise a SIGPIPE signal which by default crashed the program if not handled manually... More info here: How to prevent SIGPIPE or prevent the server from ending?

Community
  • 1
  • 1
0
This seems to be similar to what your trying to do, 
as shown on http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
Is this socket setup the same/similar to what your performing in your code?


/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno, clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
     if (newsockfd < 0) 
          error("ERROR on accept");
     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);
     n = write(newsockfd,"I got your message",18);
     if (n < 0) error("ERROR writing to socket");
     return 0; 
}
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • Yes, it is similar, although I've got a while loop before the accept, and after the last write... Thanks, I have found the answer to my question, I will post an answer, for others to see. – user3650388 May 21 '14 at 10:26