Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.99k stars 559 forks source link

Socket::SOMAXCONN() on Solaris #8980

Open p5pRT opened 17 years ago

p5pRT commented 17 years ago

Migrated from rt.perl.org#44259 (status was 'open')

Searchable as RT44259$

p5pRT commented 17 years ago

From @schweikert

Created by @schweikert

This is a bug report for perl from david@​schweikert.ch\, generated with the help of perlbug 1.35 running under perl v5.8.8.

----------------------------------------------------------------- Socket​::SOMAXCONN() on Solaris always returns 5\, which is also the value that can be found in sys/socket.h. In reality\, Solaris supports more than 5 as backlog argument to listen() and SOMAXCONN is defined as 5 for historical reasons (I presume). The real value can be tuned at runtime and queried with the following command​:

$ ndd /dev/tcp tcp_conn_req_max_q

The consequence of the fact that Socket​::SOMAXCONN() always returns 5 on Solaris is that applications which want the highest possible value of backlog for listen()\, might call Socket​::SOMAXCONN() to find out what that value is and end up using a pretty low value for it. Net​::Server does so for example.

I propose to do one of the following​:

- Find out the real value at run-time when Socket​::SOMAXCONN() is called. I   don't know however if there is an efficient method to do this (i.e. without   calling ndd)

- Return a higher fixed value on Solaris. I think that a minimum like 128 should   be available everywhere. The default is 1024...

Thanks and Cheers David Schweikert

Perl Info ``` Flags: category=library severity=medium Site configuration information for perl v5.8.8: Configured by root at Thu Jun 14 19:28:09 MEST 2007. Summary of my perl5 (revision 5 version 8 subversion 8) configuration: Platform: osname=solaris, osvers=2.8, archname=sun4-solaris uname='sunos turbine 5.8 generic_117000-05 sun4u sparc sunw,sun-fire-v240 ' config_args='-ds -e -Dprefix=/opt/perl -Dotherlibdirs=/opt/perlm/lib:/opt/ssl/cpan/lib:/opt/bdb/cpan/lib:/opt/pgsql/cpan/lib:/opt/apach/cpan/lib:/opt/apch2/cpan/lib -Dnoextensions=DB_File -Dpager=/usr/bin/less -isR' hint=recommended, useposix=true, d_sigaction=define usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O', cppflags='-fno-strict-aliasing -pipe -I/usr/local/include' ccversion='', gccversion='3.2.3', gccosandvers='solaris2.8' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib ' libpth=/usr/local/lib /usr/lib /usr/ccs/lib libs=-lsocket -lnsl -ldb -ldl -lm -lc perllibs=-lsocket -lnsl -ldl -lm -lc libc=/lib/libc.so, so=so, useshrplib=false, libperl=libperl.a gnulibc_version='' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' ' cccdlflags='-fPIC', lddlflags='-G -L/usr/local/lib' Locally applied patches: @INC for perl v5.8.8: /opt/perl/lib/5.8.8/sun4-solaris /opt/perl/lib/5.8.8 /opt/perl/lib/site_perl/5.8.8/sun4-solaris /opt/perl/lib/site_perl/5.8.8 /opt/perl/lib/site_perl /opt/perlm/lib/sun4-solaris /opt/perlm/lib /opt/ssl/cpan/lib/5.8.8/sun4-solaris /opt/ssl/cpan/lib/5.8.8 /opt/ssl/cpan/lib /opt/bdb/cpan/lib/5.8.8/sun4-solaris /opt/bdb/cpan/lib/5.8.8 /opt/bdb/cpan/lib /opt/pgsql/cpan/lib/5.8.8/sun4-solaris /opt/pgsql/cpan/lib/5.8.8 /opt/pgsql/cpan/lib /opt/apach/cpan/lib/5.8.8/sun4-solaris /opt/apach/cpan/lib/5.8.8 /opt/apach/cpan/lib /opt/apch2/cpan/lib . Environment for perl v5.8.8: HOME=/net/users/dws LANG (unset) LANGUAGE (unset) LD_LIBRARY_PATH (unset) LOGDIR (unset) PATH=/net/users/dws/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/openwin/bin:/usr/ccs/bin:/usr/ucb:/opt/base/bin PERL_BADLANG (unset) SHELL=/bin/bash ```
p5pRT commented 17 years ago

From @nwc10

On Mon\, Jul 30\, 2007 at 06​:09​:12AM -0700\, David Schweikert wrote​:

Socket​::SOMAXCONN() on Solaris always returns 5\, which is also the value that can be found in sys/socket.h. In reality\, Solaris supports more than 5 as backlog argument to listen() and SOMAXCONN is defined as 5 for historical reasons (I presume). The real value can be tuned at runtime and queried with the following command​:

$ ndd /dev/tcp tcp_conn_req_max_q

How does Solaris document that a C program should query this value? By running that command via popen() and parsing the result? Or a more direct way?

Nicholas Clark

p5pRT commented 17 years ago

The RT System itself - Status changed from 'new' to 'open'

p5pRT commented 17 years ago

From @smpeters

On Mon\, Jul 30\, 2007 at 07​:00​:57PM +0100\, Nicholas Clark wrote​:

On Mon\, Jul 30\, 2007 at 06​:09​:12AM -0700\, David Schweikert wrote​:

Socket​::SOMAXCONN() on Solaris always returns 5\, which is also the value that can be found in sys/socket.h. In reality\, Solaris supports more than 5 as backlog argument to listen() and SOMAXCONN is defined as 5 for historical reasons (I presume). The real value can be tuned at runtime and queried with the following command​:

$ ndd /dev/tcp tcp_conn_req_max_q

How does Solaris document that a C program should query this value? By running that command via popen() and parsing the result? Or a more direct way?

This is very old\, but seems very relevant...

  http​://www.usenix.org/publications/perl/perl15.html

  On almost every socket implementation in existence\, the maximum queue length   that you can set is 5 (so handle incoming connection requests quickly!)\, and   SOMAXCONN (another helpful constant from Socket.pm) is usually set to 5. If   you try to set the queue length to a value above 5\, the operating system   silently throttles the queue length back to the maximum value. Solaris 2.x   is the only modern operating system that I am aware of where you can   meaningfully specify queue length values that are greater than 5 (though   interestingly SOMAXCONN is still given as 5 in the Solaris 2.x system   header files).

Steve Peters steve@​fisharerojo.org

p5pRT commented 17 years ago

From @schweikert

On Mon\, Jul 30\, 2007 at 11​:23​:26 -0700\, Nicholas Clark via RT wrote​:

How does Solaris document that a C program should query this value? By running that command via popen() and parsing the result? Or a more direct way?

It is not documented and I don't think that it can be done without calling ndd :-(

However\, in the "Solaris Tunable Parameters Reference Manual" it is written that the default for that parameter is 128. It can be changed\, but most likely to increase it\, so it should be safe to assume that it is everywhere at least 128.

I was courious to see if the "tcp_conn_req_max_q" was also relevant to Unix domain sockets and had a look at the OpenSolaris source code. It isn't​: the maximum queue size for Unix domain sockets is fixed and defined to be 4096 (in OpenSolaris\, not sure about other Solaris versions). The parameter is called TL_MAXQLEN and I have found it here​: /usr/src/uts/common/io/tl.c

I have also seen in the source code that the backlog parameter is automatically adjusted to the maximum value if you give a value that is too large (for both unix and inet sockets). So it really shouldn't be a problem just returning 128 or even somethink higher.

Cheers David

p5pRT commented 17 years ago

From @doughera88

On Mon\, 30 Jul 2007\, Nicholas Clark wrote​:

On Mon\, Jul 30\, 2007 at 06​:09​:12AM -0700\, David Schweikert wrote​:

Socket​::SOMAXCONN() on Solaris always returns 5\, which is also the value that can be found in sys/socket.h. In reality\, Solaris supports more than 5 as backlog argument to listen() and SOMAXCONN is defined as 5 for historical reasons (I presume). The real value can be tuned at runtime and queried with the following command​:

$ ndd /dev/tcp tcp_conn_req_max_q

How does Solaris document that a C program should query this value?

They don't\, as far as I've been able to tell.

By running that command via popen() and parsing the result? Or a more direct way?

Apparently. The query simply returns a single number\, so very little parsing is needed.

  $ /usr/sbin/ndd /dev/tcp tcp_conn_req_max_q   128

The NOTES section from the Solaris 8 man pages has the following caveats​:

  The parameters supported by each driver may change from   release to release. Like programs that read /dev/kmem\, user   programs or shell scripts that execute ndd should be   prepared for parameter names to change.

  The ioctl() command that ndd uses to communicate with   drivers is likely to change in a future release. User pro-   grams should avoid making dependencies on it.

  The meanings of many ndd parameters make sense only if you   understand how the driver is implemented.

but this one\, at least\, appears to have been stable since somewhere around Solaris 7\, so it's probably ok to try it. (It's in /usr/sbin on my machine\, which isn't in a normal user's PATH.)

--   Andy Dougherty doughera@​lafayette.edu

p5pRT commented 17 years ago

From @schweikert

On Tue\, Jul 31\, 2007 at 06​:25​:49 -0700\, Andy Dougherty via RT wrote​:

How does Solaris document that a C program should query this value? ... By running that command via popen() and parsing the result? Or a more direct way?

Apparently. The query simply returns a single number\, so very little parsing is needed.

$ /usr/sbin/ndd /dev/tcp tcp\_conn\_req\_max\_q
128

Note however that this value is only pertinent for TCP sockets and not for Unix domain sockets (like I said in my previous comment to this ticket).

Cheers David

p5pRT commented 17 years ago

From @schweikert

On Mon\, Jul 30\, 2007 at 11​:23​:26 -0700\, Nicholas Clark via RT wrote​:

How does Solaris document that a C program should query this value? By running that command via popen() and parsing the result? Or a more direct way?

It is not documented and I don't think that it can be done without calling ndd :-(

However\, in the "Solaris Tunable Parameters Reference Manual" it is written that the default for that parameter is 128. It can be changed\, but most likely to increase it\, so it should be safe to assume that it is everywhere at least 128.

I was courious to see if the "tcp_conn_req_max_q" was also relevant to Unix domain sockets and had a look at the OpenSolaris source code. It isn't​: the maximum queue size for Unix domain sockets is fixed and defined to be 4096 (in OpenSolaris\, not sure about other Solaris versions). The parameter is called TL_MAXQLEN and I have found it here​: /usr/src/uts/common/io/tl.c

I have also seen in the source code that the backlog parameter is automatically adjusted to the maximum value if you give a value that is too large (for both unix and inet sockets). So it really shouldn't be a problem just returning 128 or even somethink higher.

Cheers David

p5pRT commented 17 years ago

From @schweikert

On Tue\, Jul 31\, 2007 at 06​:25​:49 -0700\, Andy Dougherty via RT wrote​:

How does Solaris document that a C program should query this value? ... By running that command via popen() and parsing the result? Or a more direct way?

Apparently. The query simply returns a single number\, so very little parsing is needed.

$ /usr/sbin/ndd /dev/tcp tcp\_conn\_req\_max\_q
128

Note however that this value is only pertinent for TCP sockets and not for Unix domain sockets (like I said in a previous comment to this ticket).

Cheers David