libserver(3)           FreeBSD Library Functions Manual           libserver(3)

     libserver - Generic Server Library

     #include <libserver.h>
     (-pthread) -I/usr/local/include -L/usr/local/lib -lserver(threads)

     Libserver supplies 3 libraries that implement generic servers.  The
     libraries perform network and concurrency tasks.  You supply code to
     service connections.  All 3 libraries service TCP or UNIX-domain
     connections.  Separate libraries implement multi-process, multi-threaded,
     and event-driven servers.  This manual documents the multi-process and
     multi-threaded libraries.  The event-driven library is described in the
     "libserverevents" manual.

     To create a multi-process server, link with -lserver.  To create a multi-
     threaded server, link with -lserverthreads.

     Example echo servers are included in the libserver source distribution.

     The libraries provide your server's "main" function.  You define 4
     functions to match the following prototypes.

     void serv_init_func();
     void serv_exit_func();
     void serv_worker_init_func();
     void serv_service_connection( FILE * );

     Do not define any other global symbol beginning with the five characters
     'serv_' because the library reserves that namespace.

     One master process/thread grows and shrinks a pool of workers to service
     connections.  Workers call serv_service_connection() once to service each
     connection that they accept.  Workers close connections when
     serv_service_connection() returns.

     serv_service_connection() is invoked with the FILE pointer of a buffered
     stream that is connected to the client.  You use the standard buffered IO
     functions to communicate with the client.  If you want to use non-
     buffered IO, use the fileno() function to determine the descriptor that
     is associated with the FILE pointer.  Do not close the FILE pointer or
     its underlying descriptor, or you will crash your server.

     In serv_init_func() perform the initialization tasks your server needs to
     do once at server start-up before any workers are created.

     The library calls serv_init_func():

     o   after changing to the directory specified by the -r command line

     o   before attempting to change the server's user and group to the values
         specified by the command line options.  If the server starts as root
         serv_init_func(), executes as root.

     o   before the server becomes a daemon and starts listening for
         connections.  The standard streams are connected to the terminal from
         which the server was started.  Error and informative messages should
         be sent to the terminal.

     Threaded servers typically want small thread stacks.  The system default
     is 2M.  Set the stack size for threaded servers with
     serv_set_stack_size().  The function is only available in the threaded
     library and can only be called from inside serv_init_func().

     int serv_set_stack_size( int );

     The function returns 0 on success and 1 on error.  On error, an error
     message is printed to stderr.

     You must ensure that the kernal tunable kern.threads.max_threads_per_proc
     is set to a value appropriate for your server.  The default value is
     1500.  The variable can be set at system start by putting an assignment
     into /etc/sysctl.conf.


     If you have exit handlers you would like to register to run before the
     server exits, do not invoke atexit() from serv_init_func().  If you do
     so, your handlers are run when the server becomes a daemon.  The server
     forks to create a new session.  The dying parent process will call your
     handlers when it exits.  Instead, call your cleanup code from

     If you need to invoke worker-specific cleanup code in a multi-process
     server, you can install your cleanup handlers with atexit() inside

     If you need to invoke worker-specific cleanup code in a multi-threaded
     server, you can call your cleanup code from the destructor functions of
     your thread-specific keys.

     Call serv_set_name() inside serv_init_func() to set the server's name.

     void serv_set_name( char * );

     If not set the server's name defaults to "server".  The server's name is
     used in two ways:

     o   When the server is running, stderr is connected to /dev/null.  Errors
         must are reported with syslog(3).  The library calls openlog() with
         the server's name as argument to ensure that log entries are
         identified by the server's name.

     o   The server's pidfile is written to /var/run/ if the server is started
         as root.  The filename is the server's name with ".pid" appended to
         it.  This file is used by rc.d scripts to stop the server.  A sample
         script is included in the libserver distribution.

     In serv_init_func(), you can install a function for the master to invoke
     periodically with:

     void serv_set_periodic( void (*)(), int );

     The library calls the function pointed to by first argument when the
     number of seconds specified by the second argument have elapsed and then
     again repeatedly when that number of seconds has elapsed since the last

     In serv_worker_init_func() perform the initialization tasks each worker
     needs to perform independently of the master.  For example, open unique
     database connections for each worker in serv_worker_init_func().

     The library calls serv_worker_init_func() after:

     o   the user and group of the process have been changed to the values
         specified by the -u and -g command line options.

     o   the standard streams are connected to /dev/null.  Errors must be
         reported with syslog(3).

     Both libraries need to catch SIGTERM, so do not change the disposition of
     that signal.

     The multi-threaded library additionally needs to catch SIGUSR1, so do not
     change the disposition of that signal in multi-threaded servers.

     Upon receipt of SIGBUS or SIGSEGV, libserver restarts servers with a call
     to execv(3).  If you want to do something else, install your own handler.

     If your server starts as root and changes user and group, the library
     will be unable to restart if your server is not executable by the user or

     The library will be unable to perform the operations that require root
     privileges after restart unless you turn on the setuid bit of the server
     (chmod u=+s).

     You can examine the following configuration variables from your code, but
     you must not modify them.   See the CONFIGURATION section for more

     char *serv_config_file;
     char *serv_root_dir;
     char *serv_interface;
     char *serv_port;
     char *serv_user;
     char *serv_group;

     serv_config_file  points to the value passed to the -f option.  Defaults
                       to NULL.

     serv_root_dir     points to the value passed to the -r option.  Defaults
                       to NULL.

     serv_interface    points to the value passed to the -i option.  Defaults
                       to "".

     serv_port         points to the value passed as argument to the -p
                       option.  Defaults to "1966".

     serv_user         points to the value passed as argument to the -u
                       option.  Defaults to "nobody".

     serv_group        points to the value passed as argument to the -g
                       option.  Defaults to "nobody".

     If a worker in a threaded server encounters an unrecoverable error, the
     thread must call serv_thread_exit() and NOT pthread_exit().

     void serv_thread_exit();

     To create and manage shared data use the pthread thread-specific data
     functions.  The following are the minimal set of functions that you need
     to understand.  All are documented in manual pages.


     Each thread maps keys to its thread-specific storage space.

     o   In scgi_init_func(), create your keys with pthread_key_create().
         Pass a destructor function to pthread_key_create() to free the space
         workers associate with keys, or your server will leak memory on
         thread termination.

     o   In scgi_worker_init_func(), malloc(3) the current thread's thread-
         specific storage and install it with pthread_setspecific().

     o   In scgi_request_handler(), retrieve your thread-specific storage with
         pthread_getspecific().  Put fresh data in your storage as you like in
         each invocation of scgi_request_handler().

     o   Release any dynamically allocated storage that are not freed by your
         keys' destructors before returning from scgi_request_handler().

     If is started as root, libserver writes its pidfile into /var/run/.  Stop
     libserver with a SIGTERM.  Libserver stops gracefully.  Idle workers exit
     immediately.  Workers with established connections continue to service
     those connections until they close.  To kill a server outright, send it a

     A sample control script, server.rcfile, is provided in the libserver
     distribution.  To use the script, replace all occurrences of "server"
     with the value you pass to serv_set_name().  Rename the script to the
     same value.  Install the script in /usr/local/etc/rc.d.

     Add the following 2 variables to /etc/rc.conf.  Substitute your server's
     name for "server":

     server_flags="-u www -g www -r /usr/local/server"

     If "enable" is set to "YES", the server is started at system start.  Use
     the following control commands.

     /usr/local/etc/rc.d/server start
     /usr/local/etc/rc.d/server stop
     /usr/local/etc/rc.d/server restart
     /usr/local/etc/rc.d/server status

     If you do not want the server started on system start, then set


     Use the following control commands.

     /usr/local/etc/rc.d/server forcestart
     /usr/local/etc/rc.d/server forcestop
     /usr/local/etc/rc.d/server forcerestart
     /usr/local/etc/rc.d/server forcestatus

     The following command line options are recognized by libserver servers.
     All of these are optional.

     -r  User the -r option to specify the server root directory.  Libserver
         chdir(2)s there.

     -l  By default, the library listens on all TCP interfaces it can find
         capable of IPv4 or IPv6.  The -l option instructs the library to
         listen on a UNIX-domain socket instead.  Specify the path to the
         socket as argument.  The server creates the socket when it starts,
         unlinking it first if it already exists in the filesystem.  The owner
         and group of the socket are changed to the values of the -u and -g
         options.  The permisssions of the socket are set to srwxrwx---.  You
         cannot specify the -l option together with the -p or -i options.

     -p  The -p option specifies the port to listen on.  This defaults to
         1966.  To bind to a port lower than 1024, the server must be started
         as root.

     -i  By default, libserver accepts connections on all interfaces it can
         find capable of IPv4 or IPv6.  The -i option limits libserver to
         accepting connections from a specified interface.  Pass the IP
         address of the desired interface as argument.

     -n  The -n options specifies the number of idle workers the master keeps
         ready.  the value defaults to 5.  The library actually allows the
         number of idle workers to reach half this value before it creates

     -m  The -m option specifies the maximum number of workers which may be
         running at any time.  The value defaults to 25.  This value is the
         maximum number of simultaneous connections a server can accept.  The
         value specified must be equal to or greater than the value specified
         for -n.

     -q  The -q option specifies the backlog of client connections queued by
         the OS kernel for the server to subsequently service.  This value
         defaults to 1024.  Note that the kernel actually uses a queue of 1.5
         times the size of the specified value.  Connections arriving when the
         queue is full are dropped by the kernel.  Libserver does not let you
         set this value to less than 1024.


     -g  The -u and the -g options are used to specify the user and group for
         the server.  Both values default to "nobody".  For libserver to
         change user, it must be started as root.

         Libserver restarts servers on receipt of SIGSEGV or SIGBUS.

         If your server starts as root and changes user and group, the library
         will be unable to restart if your server is not executable by the
         user or group.

         The library will be unable to perform the operations that require
         root privileges after restart unless you turn on the setuid bit of
         the server (chmod +s).

     -x  The -x option prevents libserver from becoming a daemon and writing
         its pidfile to /var/run/.  Libserver runs in the foreground.  Stderr
         is connected to the terminal so that diagnostic output can be sent

     -t  The -t option causes servers to exit immediately when they receive
         SIGTERM.  Normally, servers postpone exiting until all established
         connections have closed naturally.

     -f  The -f option takes a filename as argument.  Libserver assigns the
         filename to the global character pointer serv_config_file.  This
         enables code in serv_init_func() and serv_worker_init_func() to
         access a configuration file.

     James Bailie <>

                               Thu Jan 04, 2018