1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** rpc/runtime/comfork_cma.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Include CMA atfork grodiness. 90** 91** 92*/ 93 94#include <commonp.h> 95#include <com.h> /* Externals for Common Services component */ 96 97#if defined(ATFORK_SUPPORTED) 98 99#if defined(CMA_INCLUDE) 100 101/* 102 * This really doesn't belong here, but is here for pragmatic reasons. 103 */ 104 105typedef void (*atfork_handler_ptr_t) (rpc_fork_stage_id_t /*stage*/); 106/* 107 * Save the address of the fork handler registered through atfork. 108 * This pointer should be saved ONLY once by rpc__cma_atfork(). If 109 * rpc__cma_atfork() is called more than once, which happens in the 110 * child context when rpc__init() is called, do not register the 111 * fork handler. 112 */ 113INTERNAL atfork_handler_ptr_t atfork_handler_ptr = NULL; 114 115INTERNAL struct atfork_user_data_t 116{ 117 unsigned32 pid; /* who registered */ 118 unsigned32 pre; /* How many times _pre_fork called */ 119 unsigned32 post_p; /* _post_fork_parent called */ 120 unsigned32 post_c; /* _post_fork_child called */ 121} atfork_user_data; 122 123/* ========================================================================= */ 124 125INTERNAL void _pre_fork ( 126 cma_t_address /*arg*/ 127 ); 128 129INTERNAL void _post_fork_child ( 130 cma_t_address /*arg*/ 131 ); 132 133INTERNAL void _post_fork_parent ( 134 cma_t_address /*arg*/ 135 ); 136 137/* ========================================================================= */ 138 139/* 140 * _ P R E _ F O R K 141 * 142 * This procedure is called by the Pthreads library prior to calling 143 * the fork/vfork system call. 144 */ 145INTERNAL void _pre_fork 146( 147 cma_t_address arg 148) 149{ 150 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 151 ("(_pre_fork) entering, pid %d, pre %d, post_p %d, post_c %d\n", 152 ((struct atfork_user_data_t *) arg)->pid, 153 ((struct atfork_user_data_t *) arg)->pre, 154 ((struct atfork_user_data_t *) arg)->post_p, 155 ((struct atfork_user_data_t *) arg)->post_c); 156 157 ((struct atfork_user_data_t *) arg)->pre++; 158 159 if (rpc_g_initialized == true) 160 (*atfork_handler_ptr)(RPC_C_PREFORK); 161 162 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 163 ("(_pre_fork) returning, pid %d, pre %d, post_p %d, post_c %d\n", 164 ((struct atfork_user_data_t *) arg)->pid, 165 ((struct atfork_user_data_t *) arg)->pre, 166 ((struct atfork_user_data_t *) arg)->post_p, 167 ((struct atfork_user_data_t *) arg)->post_c); 168} 169 170/* 171 * _ P O S T _ F O R K _ C H I L D 172 * 173 * This procedure is called in the child of a forked process immediately 174 * after the fork is performed. 175 */ 176 177INTERNAL void _post_fork_child 178( 179 cma_t_address arg 180) 181{ 182 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 183 ("(_post_fork_child) entering, pid %d, pre %d, post_p %d, post_c %d\n", 184 ((struct atfork_user_data_t *) arg)->pid, 185 ((struct atfork_user_data_t *) arg)->pre, 186 ((struct atfork_user_data_t *) arg)->post_p, 187 ((struct atfork_user_data_t *) arg)->post_c); 188 189 ((struct atfork_user_data_t *) arg)->post_c++; 190 191 if (rpc_g_initialized == true) 192 (*atfork_handler_ptr)(RPC_C_POSTFORK_CHILD); 193 194 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 195 ("(_post_fork_child) returning, pid %d, pre %d, post_p %d, post_c %d\n", 196 ((struct atfork_user_data_t *) arg)->pid, 197 ((struct atfork_user_data_t *) arg)->pre, 198 ((struct atfork_user_data_t *) arg)->post_p, 199 ((struct atfork_user_data_t *) arg)->post_c); 200} 201 202/* 203 * _ P O S T _ F O R K _ P A R E N T 204 * 205 * This procedure is called in the parent of a forked process immediately 206 * after the fork is performed. 207 */ 208 209INTERNAL void _post_fork_parent 210( 211 cma_t_address arg 212) 213{ 214 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 215 ("(_post_fork_parent) entering, pid %d, pre %d, post_p %d, post_c %d\n", 216 ((struct atfork_user_data_t *) arg)->pid, 217 ((struct atfork_user_data_t *) arg)->pre, 218 ((struct atfork_user_data_t *) arg)->post_p, 219 ((struct atfork_user_data_t *) arg)->post_c); 220 221 ((struct atfork_user_data_t *) arg)->post_p++; 222 223 if (rpc_g_initialized == true) 224 (*atfork_handler_ptr)(RPC_C_POSTFORK_PARENT); 225 226 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 227 ("(_post_fork_parent) returning, pid %d, pre %d, post_p %d, post_c %d\n", 228 ((struct atfork_user_data_t *) arg)->pid, 229 ((struct atfork_user_data_t *) arg)->pre, 230 ((struct atfork_user_data_t *) arg)->post_p, 231 ((struct atfork_user_data_t *) arg)->post_c); 232} 233 234PRIVATE void rpc__cma_atfork 235( 236 void *handler 237) 238{ 239 if (handler == NULL) 240 return; 241 242 /* 243 * Don't register it again! 244 */ 245 if (atfork_handler_ptr != NULL) 246 return; 247 248 /* 249 * Save the address of the handler routine, and register our own 250 * handlers. (see note above) 251 */ 252 atfork_handler_ptr = (atfork_handler_ptr_t) handler; 253 atfork_user_data.pid = (unsigned32) getpid(); 254 atfork_user_data.pre = 0; 255 atfork_user_data.post_p = 0; 256 atfork_user_data.post_c = 0; 257 258 cma_atfork((cma_t_address)(&atfork_user_data), _pre_fork, 259 _post_fork_parent, _post_fork_child); 260} 261#endif /* defined(CMA_INCLUDE) */ 262 263#endif /* defined(ATFORK_SUPPORTED) */ 264