You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dean Gaudet <dg...@arctic.org> on 1997/07/28 12:37:35 UTC

more solaris stuff

Ok, the test program below does essentially what apache does with the hup
patch.  That is:  socket, bind, dup. 

It runs just peachy keen on all the solaris boxes I have access to.  But
in particular, here is "showrev -a" from one of them:

Hostname: gossip
Hostid: 807ed90b
Release: 5.5.1
Kernel architecture: sun4u
Application architecture: sparc
Hardware provider: Sun_Microsystems
Domain:
Kernel version: SunOS 5.5.1 Generic 103640-03 September 1996

OpenWindows version:
OpenWindows Version 3.5.1   26 March 1996
Patch: 103663-01  Obsoletes:   Packages: SUNWcsu, SUNWhea
Patch: 103594-03  Obsoletes: , Requires:, 103663-01  Packages: SUNWcsu
Patch: 103630-01  Obsoletes:   Packages: SUNWcsu, SUNWcsr
Patch: 103680-01  Obsoletes: , Requires:, 103663-01  Packages: SUNWcsu
Patch: 103683-01  Obsoletes: , Requires:, 103663-01  Packages: SUNWcsu
Patch: 103817-01  Obsoletes:   Packages: SUNWcsu
Patch: 103582-01  Obsoletes:   Packages: SUNWcsr
Patch: 103640-01  Obsoletes:   Packages: SUNWcsr, SUNWcar
Patch: 103640-03  Obsoletes: 103658-02, Requires:, Incompatibles:  Packages: SUNWcsr, SUNWcar
Patch: 103558-05  Obsoletes: , Requires:, Incompatibles:  Packages: SUNWadmap, SUNWadmc, SUNWsadml
Patch: 103743-01  Obsoletes: , Requires:, 103663-01  Packages: SUNWfns
Patch: 103686-01  Obsoletes: , Requires:, 103663-01  Packages: SUNWnisu

Marc does it work for you too?

I'm going to ask the submitters for their "showrev -a" output as well.

Dean

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

void main (void)
{
    int i, s, t;
    struct sockaddr_in sa;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl (INADDR_ANY);
    sa.sin_port = htons (2718);

    for (i = 0; i < 20; ++i) {
        printf ("i = %d\n", i);
	if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
	    perror ("socket");
	    exit (1);
	}
	if (bind (s, (struct sockaddr *)&sa, sizeof (sa)) == -1) {
	    fprintf (stderr, "i = %d, bind: %s\n", i, strerror (errno));
	    exit (1);
	}
	if ((t = fcntl (s, F_DUPFD, 16)) == -1) {
	    perror ("dup");
	    exit (1);
	}
	close (s);
	close (t);
    }
    exit (0);
}


Re: more solaris stuff

Posted by Dean Gaudet <dg...@arctic.org>.
On Mon, 28 Jul 1997, Dean Gaudet wrote:

> I'm not convinced it's worth our time to figure out the exact ordering
> that works some of the time.  I did try a few other orderings not obvious
> from my test program.  I got bad results all the time.  I didn't try doing
> SO_REUSEADDR before the bind however. 

UGH.  Ok so the following works without a problem on my solaris box.  I
can't spend any more time on this today. 

Dean

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

void other_stuff (int t)
{
    int one;
    struct linger li;
    int bufsiz;

    one = 1;
    if (setsockopt(t, SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(int)) < 0) {
	perror ("SO_KEEPALIVE");
	exit (1);
    }
    one = 1;
    if (setsockopt(t, IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(int)) < 0) {
	perror ("TCP_NODELAY");
	exit (1);
    }
    li.l_onoff = 1;
    li.l_linger = 30;
    if (setsockopt(t, SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(li)) < 0) {
	perror ("SO_LINGER");
	exit (1);
    }
    bufsiz = 16384;
    if (setsockopt(t, SOL_SOCKET, SO_SNDBUF,(char *)&bufsiz,sizeof(bufsiz))<0) {
	perror ("SO_SNDBUF");
	exit (1);
    }
}

void main (void)
{
    int i, s, t;
    struct sockaddr_in sa;
    struct sockaddr sa_client;
    int clen;
    int one;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl (INADDR_ANY);
    sa.sin_port = htons (2718);

    for (i = 0; i < 20; ++i) {
        printf ("i = %d\n", i);
	if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
	    perror ("socket");
	    exit (1);
	}
	one = 1;
	if (setsockopt(s, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int))<0) {
	    perror ("SO_REUSEADDR");
	    exit (1);
	}
	if (bind (s, (struct sockaddr *)&sa, sizeof (sa)) == -1) {
	    fprintf (stderr, "i = %d, bind: %s\n", i, strerror (errno));
	    exit (1);
	}
        t = s;
	other_stuff (t);
	if (listen (t, 512) == -1) {
	    perror ("listen");
	    exit (1);
	}
	if ((t = fcntl (s, F_DUPFD, 16)) == -1) {
	    perror ("dup");
	    exit (1);
	}
	close (s);
        clen = sizeof (sa_client);
	s = accept (t, &sa_client, &clen);
	if (s < 0) {
	    perror ("accept");
	} else {
	    close (s);
	}
	close (t);
	/*sleep (20);*/
    }
    exit (0);
}



Re: more solaris stuff

Posted by Dean Gaudet <dg...@arctic.org>.
I'm not convinced it's worth our time to figure out the exact ordering
that works some of the time.  I did try a few other orderings not obvious
from my test program.  I got bad results all the time.  I didn't try doing
SO_REUSEADDR before the bind however. 

I've removed the solaris_hup patch, but didn't update the known bugs page
yet. 

Dean

On Mon, 28 Jul 1997, Marc Slemko wrote:

> No.  You are still missing the SO_REUSEADDR _before_ the bind(),
> but after the socket().  Add that, and you just get the odd behavior
> of the socket just being in BOUND second time around, not in LISTEN
> like it should be.  ie. first time through, it will accept a
> connection.  Second time through, it will not give any errors but
> the socket will be in BOUND state not LISTEN and won't accept
> connections.

This seems worse than getting "Address in use".

> This is the same thing I was seeing with Apache under Solaris when I added
> lots of Listen directives at once for ports that had been bound to before
> by the same process and did a HUP.
> 
> > We should never dup a socket under solaris.  Even with SIGUSR1 it's a
> 
> I'm not convinced of that.  I will look at the test program further and
> perhaps bounce it off someone at Sun.

Well even if you reorder SO_REUSEADDR you can't restart the server right?

Dean


Re: more solaris stuff

Posted by Marc Slemko <ma...@worldgate.com>.
On Mon, 28 Jul 1997, Dean Gaudet wrote:

> On Mon, 28 Jul 1997, Marc Slemko wrote:
> 
> > On Mon, 28 Jul 1997, Dean Gaudet wrote:
> > 
> > > Ok, the test program below does essentially what apache does with the hup
> > > patch.  That is:  socket, bind, dup. 
> > 
> > No.  You are missing the critical step of accepting connections.
> 
> Ya know, I realised this last night a little too late.  I never tested any
> of this with an accepted connection.  Boy was I being silly, solaris
> sucks.  FWIW the SO_REUSEADDR probably isn't important either.  I copied
> all of the make_sock stuff into my test program... and the only thing I
> don't have is an accept().  And when I add it, it fails spectacularly on
> my system. 
> 
> It not only fails to rebind the next time around, I cannot even bind to
> that port if I run the program again.  Test program included below. 
> Solaris is supremely lame. 

No.  You are still missing the SO_REUSEADDR _before_ the bind(),
but after the socket().  Add that, and you just get the odd behavior
of the socket just being in BOUND second time around, not in LISTEN
like it should be.  ie. first time through, it will accept a
connection.  Second time through, it will not give any errors but
the socket will be in BOUND state not LISTEN and won't accept
connections.

This is the same thing I was seeing with Apache under Solaris when I added
lots of Listen directives at once for ports that had been bound to before
by the same process and did a HUP.

> We should never dup a socket under solaris.  Even with SIGUSR1 it's a

I'm not convinced of that.  I will look at the test program further and
perhaps bounce it off someone at Sun.


Re: more solaris stuff

Posted by Dean Gaudet <dg...@arctic.org>.

On Mon, 28 Jul 1997, Marc Slemko wrote:

> On Mon, 28 Jul 1997, Dean Gaudet wrote:
> 
> > Ok, the test program below does essentially what apache does with the hup
> > patch.  That is:  socket, bind, dup. 
> 
> No.  You are missing the critical step of accepting connections.

Ya know, I realised this last night a little too late.  I never tested any
of this with an accepted connection.  Boy was I being silly, solaris
sucks.  FWIW the SO_REUSEADDR probably isn't important either.  I copied
all of the make_sock stuff into my test program... and the only thing I
don't have is an accept().  And when I add it, it fails spectacularly on
my system. 

It not only fails to rebind the next time around, I cannot even bind to
that port if I run the program again.  Test program included below. 
Solaris is supremely lame. 

We should never dup a socket under solaris.  Even with SIGUSR1 it's a
problem as soon as the httpd exits.  I just verified this. 

My suggestion is to disable the slack call entirely for sockets for
solaris < 260. 

I'll work up a patch and revamp the known_problems page. 

Dean

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

void other_stuff (int t)
{
    int one;
    struct linger li;
    int bufsiz;

    one = 1;
    if (setsockopt(t, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
	perror ("SO_REUSEADDR");
	exit (1);
    }
    one = 1;
    if (setsockopt(t, SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(int)) < 0) {
	perror ("SO_KEEPALIVE");
	exit (1);
    }
    one = 1;
    if (setsockopt(t, IPPROTO_TCP,TCP_NODELAY,(char *)&one,sizeof(int)) < 0) {
	perror ("TCP_NODELAY");
	exit (1);
    }
    li.l_onoff = 1;
    li.l_linger = 30;
    if (setsockopt(t, SOL_SOCKET,SO_LINGER,(char *)&li,sizeof(li)) < 0) {
	perror ("SO_LINGER");
	exit (1);
    }
    bufsiz = 16384;
    if (setsockopt(t, SOL_SOCKET, SO_SNDBUF,(char *)&bufsiz,sizeof(bufsiz))<0) {
	perror ("SO_SNDBUF");
	exit (1);
    }
    if (listen (t, 512) == -1) {
	perror ("listen");
	exit (1);
    }
}

void main (void)
{
    int i, s, t;
    struct sockaddr_in sa;
    struct sockaddr sa_client;
    int clen;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl (INADDR_ANY);
    sa.sin_port = htons (2719);

    for (i = 0; i < 20; ++i) {
        printf ("i = %d\n", i);
	if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
	    perror ("socket");
	    exit (1);
	}
	if (bind (s, (struct sockaddr *)&sa, sizeof (sa)) == -1) {
	    fprintf (stderr, "i = %d, bind: %s\n", i, strerror (errno));
	    exit (1);
	}
	if ((t = fcntl (s, F_DUPFD, 255)) == -1) {
	    perror ("dup");
	    exit (1);
	}
	close (s);
	other_stuff (t);
        clen = sizeof (sa_client);
	s = accept (t, &sa_client, &clen);
	if (s < 0) {
	    perror ("accept");
	} else {
	    close (s);
	}
	close (t);
	sleep (20);
    }
    exit (0);
}



Re: more solaris stuff

Posted by Marc Slemko <ma...@worldgate.com>.
On Mon, 28 Jul 1997, Dean Gaudet wrote:

> Ok, the test program below does essentially what apache does with the hup
> patch.  That is:  socket, bind, dup. 

No.  You are missing the critical step of accepting connections.

> Marc does it work for you too?

Yes, but not if I change it to the below.  The below is what we have.
We need to move the setsockopt(), have the submitters try it with that,
then go from there.

showrev -a from my test machine included below.  Also have a
couple of dozen sparcs I can test on.

Hostname: devil
Hostid: 1e8fac8c
Release: 5.5.1
Kernel architecture: i86pc
Application architecture: i386
Hardware provider: 
Domain: 
Kernel version: SunOS 5.5.1 Generic 103641-08 March 1997

OpenWindows version: 
OpenWindows Version 3.5.1   21 October 1996
Patch: 103702-04  Obsoletes:   Packages: SUNWkvm, SUNWcar
Patch: 103664-07  Obsoletes: 103684-01  Packages: SUNWcsu, SUNWcsr, SUNWhea
Patch: 103595-10  Obsoletes:   Packages: SUNWcsu
Patch: 103601-13  Obsoletes: 103610-02  Packages: SUNWcsu, SUNWcsr
Patch: 103613-26  Obsoletes: 103616-04, 103655-01  Packages: SUNWcsu, SUNWcsr, SUNWarc, SUNWnisu, SUNWsutl
Patch: 103631-09  Obsoletes:   Packages: SUNWcsu, SUNWcsr
Patch: 103641-08  Obsoletes: 103659-02, 103921-05  Packages: SUNWcsu, SUNWcsr, SUNWcar
Patch: 103681-01  Obsoletes:   Packages: SUNWcsu
Patch: 103697-02  Obsoletes:   Packages: SUNWcsu, SUNWcsr
Patch: 103818-01  Obsoletes:   Packages: SUNWcsu
Patch: 104267-01  Obsoletes:   Packages: SUNWcsu
Patch: 104318-01  Obsoletes:   Packages: SUNWcsu
Patch: 104332-03  Obsoletes:   Packages: SUNWcsu
Patch: 104335-01  Obsoletes:   Packages: SUNWcsu
Patch: 104434-02  Obsoletes:   Packages: SUNWcsu
Patch: 104614-01  Obsoletes:   Packages: SUNWcsu
Patch: 104655-01  Obsoletes:   Packages: SUNWcsu
Patch: 104693-01  Obsoletes:   Packages: SUNWcsu
Patch: 104737-01  Obsoletes:   Packages: SUNWcsu
Patch: 104777-01  Obsoletes:   Packages: SUNWcsu, SUNWarc
Patch: 104969-01  Obsoletes:   Packages: SUNWcsu
Patch: 105051-01  Obsoletes:   Packages: SUNWcsu, SUNWscpu
Patch: 103007-06  Obsoletes:   Packages: SUNWcsu, SUNWcsr, SUNWhea
Patch: 103679-07  Obsoletes:   Packages: SUNWcsr, SUNWhea
Patch: 104346-02  Obsoletes:   Packages: SUNWcsr
Patch: 104780-01  Obsoletes:   Packages: SUNWcsr
Patch: 104894-01  Obsoletes:   Packages: SUNWcsr
Patch: 104359-03  Obsoletes:   Packages: SUNWcar, SUNWhea
Patch: 104241-02  Obsoletes:   Packages: SUNWxwplt, SUNWxwslb
Patch: 104011-01  Obsoletes:   Packages: SUNWvolu
Patch: 104195-04  Obsoletes:   Packages: SUNWmfrun
Patch: 103559-07  Obsoletes:   Packages: SUNWadmap, SUNWadmc, SUNWsadml
Patch: 103881-04  Obsoletes:   Packages: SUNWkcsrt
Patch: 102571-10  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 102575-02  Obsoletes:   Packages: SUNWman
Patch: 102576-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 102577-08  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103087-02  Obsoletes:   Packages: SUNWman, SUNWpsdcr
Patch: 103102-07  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103360-04  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103361-06  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103370-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103716-02  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103756-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103773-04  Obsoletes:   Packages: SUNWman, SUNWos86r, SUNWos86u
Patch: 103887-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103904-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 103906-08  Obsoletes:   Packages: SUNWman, SUNWpsdcr
Patch: 104032-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104189-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104251-03  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104276-01  Obsoletes:   Packages: SUNWman
Patch: 104425-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104465-06  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104501-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104502-02  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104684-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 104809-01  Obsoletes:   Packages: SUNWman, SUNWos86r
Patch: 102573-03  Obsoletes:   Packages: SUNWos86r
Patch: 102574-02  Obsoletes:   Packages: SUNWos86r
Patch: 103099-01  Obsoletes:   Packages: SUNWos86r
Patch: 103100-02  Obsoletes:   Packages: SUNWos86r
Patch: 103890-02  Obsoletes:   Packages: SUNWos86r, SUNWpsh
Patch: 103905-01  Obsoletes:   Packages: SUNWos86r
Patch: 104006-02  Obsoletes:   Packages: SUNWos86r
Patch: 104503-01  Obsoletes:   Packages: SUNWos86r
Patch: 104504-01  Obsoletes:   Packages: SUNWos86r
Patch: 104784-01  Obsoletes:   Packages: SUNWos86r
Patch: 104837-01  Obsoletes:   Packages: SUNWos86r
Patch: 103500-07  Obsoletes:   Packages: SUNWos86r, SUNWos86u, SUNWpmi, SUNWxwpls
Patch: 104517-03  Obsoletes:   Packages: SUNWapppu
Patch: 103744-01  Obsoletes:   Packages: SUNWfns
Patch: 103687-02  Obsoletes:   Packages: SUNWnisu
Patch: 103359-05  Obsoletes: 103022-02  Packages: SUNWpsdcr
Patch: 103486-01  Obsoletes:   Packages: SUNWpsdcr
Patch: 103522-01  Obsoletes:   Packages: SUNWpsdcr
Patch: 103633-01  Obsoletes:   Packages: SUNWpsdcr
Patch: 103888-01  Obsoletes:   Packages: SUNWpsdcr
Patch: 104634-02  Obsoletes:   Packages: SUNWpsdcr
Patch: 103550-03  Obsoletes:   Packages: SUNWpsh, SUNWpsdir
Patch: 103675-04  Obsoletes: 103088-02  Packages: SUNWpsh, SUNWpsdir
Patch: 103689-05  Obsoletes:   Packages: SUNWpsdir
Patch: 104350-01  Obsoletes:   Packages: SUNWpsdir
Patch: 103765-04  Obsoletes:   Packages: SUNWpcelx
Patch: 103994-01  Obsoletes:   Packages: SUNWpcser


Program below:

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

void main (void)
{
    int i, s, t;
    struct sockaddr_in sa;
    struct sockaddr sa_client;

    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = htonl (INADDR_ANY);
    sa.sin_port = htons (2718);

    for (i = 0; i < 10; ++i) {
	int clen = sizeof(sa_client);
	int one = 1;
        printf ("i = %d\n", i);
	if ((s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
	    perror ("socket");
	    exit (1);
	}
	if (bind (s, (struct sockaddr *)&sa, sizeof (sa)) == -1) {
	    fprintf (stderr, "i = %d, bind: %s\n", i, strerror (errno));
	    exit (1);
	}
	if ((t = fcntl (s, F_DUPFD, 16)) == -1) {
	    perror ("dup");
	    exit (1);
	}
	close (s);

	if (setsockopt(t, SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(int)) < 0) {
	    perror("setsockopt");
	    exit(1);
	}


	listen(t, 512);
	accept(t, &sa_client, &clen);
	close (t);
    }
    exit (0);
}