You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by "Roy T. Fielding" <fi...@kiwi.ICS.UCI.EDU> on 1997/03/11 09:30:13 UTC

[PATCH]: "kernel panics and dumps core" on SunOS 4.x (fwd)

>Date: Mon Mar  3  7:59:41 1997
>From: chrisd@name.net
>To: apache-bugs%apache.org@organic.com
>Subject: [BUG]: "kernel panics and dumps core" on SunOS 4.x
>
>Submitter: chrisd@name.net
>Operating system: SunOS 4.x, version: 
>Version of Apache Used: 1.2b7
>
>Symptoms:
>--
>SunOs 4.1.3 kernel panics and dumps core,
>machine shuts down.  No info is written to log
>files and no httpd core is created.  Here's the
>syslog entry:
>
>BAD TRAP
>pid 11358, `httpd': Data fault
>kernel read fault at addr=0x20, pme=0x0
>Sync Error Reg 80<INVALID>
>pc=0xf801e7d8, sp=0xf8620da0, psr=0x114000c6, context=0x8
>g1-g7: f801e7cc, 4b000, ffffff00, 48000000, f8621000, 0, 0
>Begin traceback... sp = f8620da0
>Called from f805d534, fp=f8620e00, args=1 ff66f50c 6 1 f8620eb0 0
>Called from f8060294, fp=f8620e60, args=ff66f50c 6 1 ff66fb00 0 ff66fb00
>Called from f810ac60, fp=f8620ec0, args=f8620fe0 348 f8143ab8 f836a1c8
>ff66fb00
>f8620fe0
>Called from f8005a54, fp=f8620f58, args=f8621000 f8620fb4 f8620fe0 f8621000
>f862
>1000 f8620fb4
>Called from 4e7c, fp=f7fffca8, args=11 6 1 f7fffd0c 4 1
>End traceback...
>panic: Data fault
>
>One of our Unix gurus, Rens Troost, reports:
>
>Looking into the coredumps reveals that in fact the same code path is
>killing the server each time; the relevant part of the stack trace:
>
>f85eee60 f8060294     _setsockopt+  dc  f85eefe0 348 f8143ab8 f83522a4
>
>Looks like something in Apache is passing a bad value to setsockopt(),
>and the argument is not being properly validated.

Thank you for the detailed report -- that narrowed it down to a
specific line of code (the setting of TCP_NODELAY) and even reveals
the cause in the argument list.  The optlen parameter is being set to 0
instead of sizeof(int), probably due to a compiler optimization replacing
the const int with a literal value.  I am betting that the following
patch will fix it.  [Note to Apache folks -- this patch overlaps and
conflicts with Dean's error handling patch, but only coincidentally.]

.....Roy


Index: http_main.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_main.c,v
retrieving revision 1.128
diff -c -r1.128 http_main.c
*** http_main.c	1997/03/11 06:04:39	1.128
--- http_main.c	1997/03/11 08:20:18
***************
*** 1552,1567 ****
      /* The Nagle algorithm says that we should delay sending partial
       * packets in hopes of getting more data.  We don't want to do
       * this; we are not telnet.  There are bad interactions between
!      * P-HTTP and Nagle's algorithm that have very severe performance
!      * penalties.  (Failing to do disable Nagle is not much of a
       * problem with simple HTTP.)
       *
       * In spite of these problems, failure here is not a shooting offense.
       */
!     const int just_say_no = 1;
  
!     if (0 != setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&just_say_no,
! 			sizeof just_say_no))
  	fprintf(stderr, "httpd: could not set socket option TCP_NODELAY\n");
  }
  #else
--- 1552,1567 ----
      /* The Nagle algorithm says that we should delay sending partial
       * packets in hopes of getting more data.  We don't want to do
       * this; we are not telnet.  There are bad interactions between
!      * persistent connections and Nagle's algorithm that have very severe
!      * performance penalties.  (Failing to disable Nagle is not much of a
       * problem with simple HTTP.)
       *
       * In spite of these problems, failure here is not a shooting offense.
       */
!     int just_say_no = 1;
  
!     if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&just_say_no,
!                    sizeof(int)) < 0)
  	fprintf(stderr, "httpd: could not set socket option TCP_NODELAY\n");
  }
  #else
***************
*** 1842,1849 ****
  make_sock(pool *pconf, const struct sockaddr_in *server)
  {
      int s;
!     const int one = 1;
!     const int keepalive_value = 1;  
  
      if ((s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
          perror("socket");
--- 1842,1848 ----
  make_sock(pool *pconf, const struct sockaddr_in *server)
  {
      int s;
!     int one = 1;
  
      if ((s = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) == -1) {
          perror("socket");
***************
*** 1855,1868 ****
      
  #ifndef MPE
  /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
!     if((setsockopt(s, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)))
!        == -1) {
  	perror("setsockopt(SO_REUSEADDR)");
  	fprintf(stderr,"httpd: could not set socket option SO_REUSEADDR\n");
          exit(1);
      }
!     if((setsockopt(s, SOL_SOCKET,SO_KEEPALIVE,(char *)&keepalive_value,
!         sizeof(keepalive_value))) == -1) {
  	perror("setsockopt(SO_KEEPALIVE)"); 
          fprintf(stderr,"httpd: could not set socket option SO_KEEPALIVE\n"); 
          exit(1); 
--- 1854,1866 ----
      
  #ifndef MPE
  /* MPE does not support SO_REUSEADDR and SO_KEEPALIVE */
!     if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
  	perror("setsockopt(SO_REUSEADDR)");
  	fprintf(stderr,"httpd: could not set socket option SO_REUSEADDR\n");
          exit(1);
      }
!     one = 1;
!     if (setsockopt(s, SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(int)) < 0) {
  	perror("setsockopt(SO_KEEPALIVE)"); 
          fprintf(stderr,"httpd: could not set socket option SO_KEEPALIVE\n"); 
          exit(1); 
***************
*** 1883,1889 ****
  	li.l_linger = 900;
  
  	if (setsockopt(s, SOL_SOCKET, SO_LINGER,
! 	    (char *)&li, sizeof(struct linger)) < 0) {
  	    perror("setsockopt(SO_LINGER)");
  	    fprintf(stderr,"httpd: could not set socket option SO_LINGER\n");
  	    exit(1);
--- 1881,1887 ----
  	li.l_linger = 900;
  
  	if (setsockopt(s, SOL_SOCKET, SO_LINGER,
! 	               (char *)&li, sizeof(struct linger)) < 0) {
  	    perror("setsockopt(SO_LINGER)");
  	    fprintf(stderr,"httpd: could not set socket option SO_LINGER\n");
  	    exit(1);
***************
*** 1912,1918 ****
       * If no size is specified, use the kernel default.
       */
      if (server_conf->send_buffer_size) {
!         if((setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&server_conf->send_buffer_size, sizeof(int))) < 0) {
  	    perror("setsockopt(SO_SNDBUF), using default buffer size"); 
  	    /* Fail soft. */
  	}
--- 1910,1917 ----
       * If no size is specified, use the kernel default.
       */
      if (server_conf->send_buffer_size) {
!         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
!               (char *)&server_conf->send_buffer_size, sizeof(int)) < 0) {
  	    perror("setsockopt(SO_SNDBUF), using default buffer size"); 
  	    /* Fail soft. */
  	}