/* * Copyright (c) 2010 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Portions of this software have been released under the following terms: * * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file for any * purpose is hereby granted without fee, provided that the above * copyright notices and this notice appears in all source code copies, * and that none of the names of Open Software Foundation, Inc., Hewlett- * Packard Company or Digital Equipment Corporation be used * in advertising or publicity pertaining to distribution of the software * without specific, written prior permission. Neither Open Software * Foundation, Inc., Hewlett-Packard Company nor Digital * Equipment Corporation makes any representations about the suitability * of this software for any purpose. * * Copyright (c) 2007, Novell, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Novell Inc. nor the names of its contributors * may be used to endorse or promote products derived from this * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * @APPLE_LICENSE_HEADER_END@ */ /* ** ** NAME ** ** rpc/runtime/comfork_cma.c ** ** FACILITY: ** ** Remote Procedure Call (RPC) ** ** ABSTRACT: ** ** Include CMA atfork grodiness. ** ** */ #include <commonp.h> #include <com.h> /* Externals for Common Services component */ #if defined(ATFORK_SUPPORTED) #if defined(CMA_INCLUDE) /* * This really doesn't belong here, but is here for pragmatic reasons. */ typedef void (*atfork_handler_ptr_t) (rpc_fork_stage_id_t /*stage*/); /* * Save the address of the fork handler registered through atfork. * This pointer should be saved ONLY once by rpc__cma_atfork(). If * rpc__cma_atfork() is called more than once, which happens in the * child context when rpc__init() is called, do not register the * fork handler. */ INTERNAL atfork_handler_ptr_t atfork_handler_ptr = NULL; INTERNAL struct atfork_user_data_t { unsigned32 pid; /* who registered */ unsigned32 pre; /* How many times _pre_fork called */ unsigned32 post_p; /* _post_fork_parent called */ unsigned32 post_c; /* _post_fork_child called */ } atfork_user_data; /* ========================================================================= */ INTERNAL void _pre_fork ( cma_t_address /*arg*/ ); INTERNAL void _post_fork_child ( cma_t_address /*arg*/ ); INTERNAL void _post_fork_parent ( cma_t_address /*arg*/ ); /* ========================================================================= */ /* * _ P R E _ F O R K * * This procedure is called by the Pthreads library prior to calling * the fork/vfork system call. */ INTERNAL void _pre_fork ( cma_t_address arg ) { RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_pre_fork) entering, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); ((struct atfork_user_data_t *) arg)->pre++; if (rpc_g_initialized == true) (*atfork_handler_ptr)(RPC_C_PREFORK); RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_pre_fork) returning, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); } /* * _ P O S T _ F O R K _ C H I L D * * This procedure is called in the child of a forked process immediately * after the fork is performed. */ INTERNAL void _post_fork_child ( cma_t_address arg ) { RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_post_fork_child) entering, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); ((struct atfork_user_data_t *) arg)->post_c++; if (rpc_g_initialized == true) (*atfork_handler_ptr)(RPC_C_POSTFORK_CHILD); RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_post_fork_child) returning, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); } /* * _ P O S T _ F O R K _ P A R E N T * * This procedure is called in the parent of a forked process immediately * after the fork is performed. */ INTERNAL void _post_fork_parent ( cma_t_address arg ) { RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_post_fork_parent) entering, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); ((struct atfork_user_data_t *) arg)->post_p++; if (rpc_g_initialized == true) (*atfork_handler_ptr)(RPC_C_POSTFORK_PARENT); RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, ("(_post_fork_parent) returning, pid %d, pre %d, post_p %d, post_c %d\n", ((struct atfork_user_data_t *) arg)->pid, ((struct atfork_user_data_t *) arg)->pre, ((struct atfork_user_data_t *) arg)->post_p, ((struct atfork_user_data_t *) arg)->post_c); } PRIVATE void rpc__cma_atfork ( void *handler ) { if (handler == NULL) return; /* * Don't register it again! */ if (atfork_handler_ptr != NULL) return; /* * Save the address of the handler routine, and register our own * handlers. (see note above) */ atfork_handler_ptr = (atfork_handler_ptr_t) handler; atfork_user_data.pid = (unsigned32) getpid(); atfork_user_data.pre = 0; atfork_user_data.post_p = 0; atfork_user_data.post_c = 0; cma_atfork((cma_t_address)(&atfork_user_data), _pre_fork, _post_fork_parent, _post_fork_child); } #endif /* defined(CMA_INCLUDE) */ #endif /* defined(ATFORK_SUPPORTED) */