closing a socket causes problems---why?

closing a socket causes problems---why?

Post by mkri.. » Tue, 28 Sep 1999 04:00:00



I've been trying to port a little webserver to Linux and
can't find a solution to the following problem. Whenever
MSIE or Netscape ask for a cgi script with a POST method,
they get a "network error" when the socket gets closed.
No problems with the GET method (nor with the contents
returned by the script). While trying to identify
this, I've written the enclosed dummy server that
completely ignores all headers (thus treats GET and POST
the exact same way) and just sends back some headers (including
the content length) and 8 body bytes. This is like straight
out of networking textbooks, nothing fancy, as you can see.
It has the same problem with POST as the real server...

The problem shows if you access it with POST from Netscape when it
is running on 2.2.5-15 kernel (tried both with glibc 2.1.6
and 2.0.7). No problem on 2.0.34 kernel at home or on
HP, Sun, DEC. No problem with lynx, telnet to it, KDE file manager.
No problem if Netscape uses GET method. No problem for a very
similar dummy server written in Perl.

Can somebody please tell me what might be causing this? Did
something get broken in kernel between 2.0 and 2.2? Is it something
with certain glibc versions? Am I just missing something?
Is there any workaround known?

Any input will be much appreciated.

Thanks,


-----------------------------------------------------------------------

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define LINELEN 1023

int main(int argc, char **argv)
{
  int port = 0, on = 1, s, fd, i, j, l;
  char line[LINELEN + 1];
  struct sockaddr_in sa;
  /*  struct linger ls; */
  char msg[] = "HTTP/1.0 200 OK\n"
               "Content-Type: text/plain\n"
               "Content-Length: 8\n"
               "\n"
               "abcdefg\n";

  if (argc >= 2)
    port = atoi(argv[1]);

  if (!port)
    port = 8080;

  memset(&sa, 0, sizeof(struct sockaddr_in));
  sa.sin_port = htons(port);
  sa.sin_family = AF_INET;

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    perror("socket");
    exit(1);
  }

  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)))
    perror("setsockopt");

  /*  This doesn't help either

  ls.l_onoff = 1;
  ls.l_linger = 500;

  if (setsockopt(s, SOL_SOCKET, SO_LINGER, (const void *) &ls, sizeof(ls)))
    perror("setsockopt");
  */

  if (bind(s, (struct sockaddr *) (void *) &sa, sizeof(struct sockaddr_in))
      < 0)
  {
    perror("bind");
    exit(2);
  }

  if (listen(s, SOMAXCONN))
  {
    perror("listen");
    exit(3);
  }

  printf("Listening on port %d\n", port);

  for ( ; ; )
  {

    if ((fd = accept(s, NULL, NULL)) < 0)
    {
      perror("accept");
      exit(4);
    }

    printf("Accepted a connection on fd %d\n", fd);

    for ( ; ; )        // reading all the headers here
    {

      for (i = 0; i < LINELEN; i++)
      {

         if (read(fd, line + i, 1) < 0)
         {
           perror("read");
           exit(5);
         }

         if (line[i] == '\n')
         {
           line[i + 1] = '\0';
           printf("Just input: %s", line);
           break;
         }

      }

      if (i >= LINELEN)
      {
        printf("Line longer than %d\n", LINELEN);
        exit(6);
      }

      if (!strcmp(line, "\n") || !strcmp(line, "\r\n"))
        break;

    }

    l = strlen(msg);

    for (i = 0; i < l; i += j)
      if ((j = write(fd, msg + i, l - i)) < 0)
      {
        perror("write");
        exit(7);
      }

    if (close(fd) < 0)
    {
      perror("close");
      exit(8);
    }

  }

  return 0;     // not reached

Quote:}

 
 
 

closing a socket causes problems---why?

Post by mkri.. » Wed, 29 Sep 1999 04:00:00


I've finally isolated my problem to kernel versions:
2.0 good, 2.2 bad.

I have a trivial piece of code (dummy webserver) that
causes a "Network Error" if running on 2.2.x kernels
and accessed by Netscape or IExploder with a POST method.
No problem on 2.0.x kernels or HP, Sun, DEC machines.
The problem occurs exactly when the server does a close() on the socket.

Has anybody else encountered this problem?
This is textbook stuff, how can it fail w/ the most recent
stable kernels? (2.2.12 is the latest I could find and try.)

Any answers will be much appreciated.


P.S. For a more detailed problem description, please see my
previous post "closing a socket causes problems---why?"

---------------------------------------------------------------------

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define LINELEN 1023

int main(int argc, char **argv)
{
  int port = 0, on = 1, s, fd, i, j, l;
  char line[LINELEN + 1];
  struct sockaddr_in sa;
  /*  struct linger ls; */
  char msg[] = "HTTP/1.0 200 OK\n"
               "Content-Type: text/plain\n"
               "Content-Length: 8\n"
               "\n"
               "abcdefg\n";

  if (argc >= 2)
    port = atoi(argv[1]);

  if (!port)
    port = 8080;

  memset(&sa, 0, sizeof(struct sockaddr_in));
  sa.sin_port = htons(port);
  sa.sin_family = AF_INET;

  if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  {
    perror("socket");
    exit(1);
  }

  if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)))
    perror("setsockopt");

  /*  This doesn't help either

  ls.l_onoff = 1;
  ls.l_linger = 500;

  if (setsockopt(s, SOL_SOCKET, SO_LINGER, (const void *) &ls, sizeof(ls)))
    perror("setsockopt");
  */

  if (bind(s, (struct sockaddr *) (void *) &sa, sizeof(struct sockaddr_in))
      < 0)
  {
    perror("bind");
    exit(2);
  }

  if (listen(s, SOMAXCONN))
  {
    perror("listen");
    exit(3);
  }

  printf("Listening on port %d\n", port);

  for ( ; ; )
  {

    if ((fd = accept(s, NULL, NULL)) < 0)
    {
      perror("accept");
      exit(4);
    }

    printf("Accepted a connection on fd %d\n", fd);

    for ( ; ; )        // reading all the headers here
    {

      for (i = 0; i < LINELEN; i++)
      {

         if (read(fd, line + i, 1) < 0)
         {
           perror("read");
           exit(5);
         }

         if (line[i] == '\n')
         {
           line[i + 1] = '\0';
           printf("Just input: %s", line);
           break;
         }

      }

      if (i >= LINELEN)
      {
        printf("Line longer than %d\n", LINELEN);
        exit(6);
      }

      if (!strcmp(line, "\n") || !strcmp(line, "\r\n"))
        break;

    }

    l = strlen(msg);

    for (i = 0; i < l; i += j)
      if ((j = write(fd, msg + i, l - i)) < 0)
      {
        perror("write");
        exit(7);
      }

    if (close(fd) < 0)
    {
      perror("close");
      exit(8);
    }

  }

  return 0;     // not reached

Quote:}


 
 
 

closing a socket causes problems---why?

Post by Bob Tenne » Fri, 01 Oct 1999 04:00:00



 >I've finally isolated my problem to kernel versions:
 >2.0 good, 2.2 bad.
 >
 >I have a trivial piece of code (dummy webserver) that
 >causes a "Network Error" if running on 2.2.x kernels
 >and accessed by Netscape or IExploder with a POST method.
 >No problem on 2.0.x kernels or HP, Sun, DEC machines.
 >The problem occurs exactly when the server does a close() on the socket.
 >
 >Has anybody else encountered this problem?
 >This is textbook stuff, how can it fail w/ the most recent
 >stable kernels? (2.2.12 is the latest I could find and try.)
 >
Try 2.2.13pre14.  If it has the same problem, send your example
to the linux-kernel list.

Bob T.