2011-04-21 00:28:57 +04:00
/*
Unix SMB / CIFS implementation .
Common server globals
Copyright ( C ) Simo Sorce < idra @ samba . org > 2011
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "system/network.h"
# include <tevent.h>
enum pf_worker_status {
PF_WORKER_NONE = 0 ,
PF_WORKER_IDLE ,
PF_WORKER_ACCEPTING ,
PF_WORKER_BUSY ,
PF_WORKER_EXITING
} ;
enum pf_server_cmds {
PF_SRV_MSG_NONE = 0 ,
PF_SRV_MSG_EXIT
} ;
2011-05-16 18:23:59 +04:00
/**
* @ brief This structure is shared betwee the controlling parent and the
* the child . The parent can only write to the ' cmds ' and
* ' allowed_clients ' variables , while a child is running .
* The child can change ' status ' , and ' num_clients ' .
* All other variables are initialized by the parent before forking the
* child .
*/
2011-04-21 00:28:57 +04:00
struct pf_worker_data {
pid_t pid ;
enum pf_worker_status status ;
time_t started ;
time_t last_used ;
int num_clients ;
2011-05-06 01:56:31 +04:00
enum pf_server_cmds cmds ;
int allowed_clients ;
2011-04-21 00:28:57 +04:00
} ;
2011-05-16 18:23:59 +04:00
/**
* @ brief This is the ' main ' function called by a child right after the fork .
* It is daemon specific and should initialize and perform whatever
* operation the child is meant to do . Returning from this function will
* cause the termination of the child .
*
* @ param ev The event context
* @ param pf The mmaped area used to communicate with parent
* @ param listen_fd_size The number of file descriptors to monitor
* @ param listen_fds The array of file descriptors
* @ param lock_fd The locking file descriptor
* @ param private_data Private data that needs to be passed to the main
* function from the calling parent .
*
* @ return Returns the exit status to be reported to the parent via exit ( )
*/
2011-04-21 00:28:57 +04:00
typedef int ( prefork_main_fn_t ) ( struct tevent_context * ev ,
struct pf_worker_data * pf ,
2011-05-10 16:39:14 +04:00
int listen_fd_size ,
int * listen_fds ,
2011-04-21 00:28:57 +04:00
int lock_fd ,
void * private_data ) ;
struct prefork_pool ;
/* ==== Functions used by controlling process ==== */
2011-05-16 18:23:59 +04:00
/**
* @ brief Creates the first pool of preforked processes
*
* @ param ev_ctx The event context
* @ param mem_ctx The memory context used to hold the pool structure
* @ param listen_fd_size The number of file descriptors to monitor
* @ param listen_fds The array of file descriptors to monitor
* @ param min_children Minimum number of children that must be available at
* any given time
* @ param max_children Maximum number of children that can be started . Also
* determines the initial size of the pool .
* @ param main_fn The children ' main ' function to be called after fork
* @ param private_data The children private data .
* @ param pf_pool The allocated pool .
*
* @ return True if it was successful , False otherwise .
*/
2011-05-10 16:39:14 +04:00
bool prefork_create_pool ( struct tevent_context * ev_ctx , TALLOC_CTX * mem_ctx ,
int listen_fd_size , int * listen_fds ,
2011-04-21 00:28:57 +04:00
int min_children , int max_children ,
prefork_main_fn_t * main_fn , void * private_data ,
struct prefork_pool * * pf_pool ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Function used to attemp to expand the size of children .
*
* @ param pfp The pool structure .
* @ param new_max The new max number of children .
*
* @ return 0 if operation was successful
* ENOSPC if the mmap area could not be grown to the requested size
* EINVAL if the new max is invalid .
*
* NOTE : this funciton can easily fail if the mmap area cannot be enlarged .
* A well behaving parent MUST NOT error out if this happen .
*/
2011-05-09 12:51:47 +04:00
int prefork_expand_pool ( struct prefork_pool * pfp , int new_max ) ;
2011-04-21 00:28:57 +04:00
2011-05-16 18:23:59 +04:00
/**
* @ brief Used to prefork a number of new children
*
* @ param ev_ctx The event context
* @ param pfp The pool structure
* @ param num_children The number of children to be started
*
* @ return The number of new children effectively forked .
*
* NOTE : This method does not expand the pool , if the max number of children
* has already been forked it will do nothing .
*/
2011-04-21 00:28:57 +04:00
int prefork_add_children ( struct tevent_context * ev_ctx ,
struct prefork_pool * pfp ,
int num_children ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Commands a number fo children to stop and exit
*
* @ param pfp The pool .
* @ param num_children The number of children we need to retire .
* @ param age_limit The minimum age a child has been active to be
* considered for retirement . ( Compared against the
* ' started ' value in the pf_worker_data structure of the
* children .
*
* @ return Number of children that were signaled to stop
*
* NOTE : Only children that has no attached clients can be stopped .
* If all the available children are too young or are busy than it
* is possible that none will be asked to stop .
*/
2011-04-21 00:28:57 +04:00
int prefork_retire_children ( struct prefork_pool * pfp ,
int num_children , time_t age_limit ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Count the number of active children
*
* @ param pfp The pool .
* @ param total Returns the number of children currently alive
*
* @ return The number of children actually serving clients
*/
2011-04-21 00:28:57 +04:00
int prefork_count_active_children ( struct prefork_pool * pfp , int * total ) ;
2011-05-16 18:46:35 +04:00
2011-05-16 18:23:59 +04:00
/**
2011-05-16 18:46:35 +04:00
* @ brief Perform cleanups , like waiting ( WNOHANG ) dead children .
* MUST be called regularly from the parent main loop .
2011-05-16 18:23:59 +04:00
*
* @ param pfp The pool .
*/
2011-05-16 18:46:35 +04:00
void prefork_cleanup_loop ( struct prefork_pool * pfp ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Inform all children that they are allowed to accept ' max ' clients
* now . Use this when all children are already busy and more clients
* are trying to connect . It will allow each child to handle more than
* one client at a time , up to ' max ' .
*
* @ param pfp The pool .
* @ param max Max number of clients per child .
*/
2011-05-06 01:56:31 +04:00
void prefork_increase_allowed_clients ( struct prefork_pool * pfp , int max ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Reset the maximum allowd clients per child to 1.
* Does not reduce the number of clients actually beeing served by
* any given child , but prevents children from overcommitting from
* now on .
*
* @ param pfp The pool .
*/
2011-05-06 01:56:31 +04:00
void prefork_reset_allowed_clients ( struct prefork_pool * pfp ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Send a specific signal to all children .
* Used to send SIGHUP when a reload of the configuration is needed
* for example .
*
* @ param pfp The pool .
* @ param signal_num The signal number to be sent .
*/
2011-05-09 16:49:50 +04:00
void prefork_send_signal_to_all ( struct prefork_pool * pfp , int signal_num ) ;
2011-04-21 00:28:57 +04:00
/* ==== Functions used by children ==== */
2011-05-16 18:23:59 +04:00
/**
* @ brief Try to listen and accept on one of the listening sockets .
* Asynchronusly tries to grab the lock and perform an accept .
* Will automatically updated the ' status ' of the child and handle
* all the locking / unlocking / timingout as necessary .
* Changes behavior depending on whether the child already has other
* client connections . If not it blocks on the lock call for periods of
* time . Otherwise it loops on the lock using a timer in order to allow
* processing of the other clients requests .
*
* @ param mem_ctx The memory context on whic to allocate the request
* @ param ev The event context
* @ param pf The child / parent shared structure
* @ param listen_fd_size The number of listening file descriptors
* @ param listen_fds The array of listening file descriptors
* @ param lock_fd The locking file descriptor
* @ param addr The structure that will hold the client address on
* return
* @ param addrlen The structure length on return .
*
* @ return The tevent request pointer or NULL on allocation errors .
*/
2011-05-04 02:55:25 +04:00
struct tevent_req * prefork_listen_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct pf_worker_data * pf ,
2011-05-10 16:39:14 +04:00
int listen_fd_size ,
int * listen_fds ,
int lock_fd ,
2011-05-04 02:55:25 +04:00
struct sockaddr * addr ,
socklen_t * addrlen ) ;
2011-05-16 18:23:59 +04:00
/**
* @ brief Returns the file descriptor after the new client connection has
* been accepted .
*
* @ param req The request
* @ param fd The new file descriptor .
*
* @ return The error in case the operation failed .
*/
2011-05-04 02:55:25 +04:00
int prefork_listen_recv ( struct tevent_req * req , int * fd ) ;