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.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Include pthreads 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 99PRIVATE boolean32 rpc__fork_is_in_progress (void); 100 101/* 102 * Boolean indicating whether fork is in progress or not. 103 */ 104INTERNAL volatile boolean32 atfork_in_progress = false; 105 106/* 107 * This really doesn't belong here, but is here for pragmatic reasons. 108 */ 109 110typedef void (*atfork_handler_ptr_t) (rpc_fork_stage_id_t /*stage*/); 111 112/* 113 * Save the address of the fork handler registered through atfork. 114 * This pointer should be saved ONLY once by rpc__atfork(). If 115 * rpc__atfork() is called more than once, which happens in the 116 * child context when rpc__init() is called, do not register the 117 * fork handler. 118 */ 119 120/* 121 * Private handler state for the RPC runtime 122 */ 123INTERNAL volatile atfork_handler_ptr_t atfork_handler_ptr = NULL; 124 125INTERNAL struct atfork_user_data_t 126{ 127 pid_t pid; /* who registered */ 128 unsigned32 pre; /* How many times _pre_fork called */ 129 unsigned32 post_p; /* _post_fork_parent called */ 130 unsigned32 post_c; /* _post_fork_child called */ 131} rpc__atfork_user_data; 132 133/* ========================================================================= */ 134 135INTERNAL void _pre_fork ( 136 dce_pointer_t /*arg*/ 137 ); 138 139INTERNAL void _post_fork_child ( 140 dce_pointer_t /*arg*/ 141 ); 142 143INTERNAL void _post_fork_parent ( 144 dce_pointer_t /*arg*/ 145 ); 146 147/* ========================================================================= */ 148 149/* 150 * _ P R E _ F O R K 151 * 152 * This procedure is called by the Pthreads library prior to calling 153 * the fork/vfork system call. 154 */ 155INTERNAL void _pre_fork 156( 157 dce_pointer_t arg 158) 159{ 160 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 161 ("(_pre_fork) entering, pid %d, pre %d, post_p %d, post_c %d\n", 162 ((struct atfork_user_data_t *) arg)->pid, 163 ((struct atfork_user_data_t *) arg)->pre, 164 ((struct atfork_user_data_t *) arg)->post_p, 165 ((struct atfork_user_data_t *) arg)->post_c)); 166 167 atfork_in_progress = true; 168 ((struct atfork_user_data_t *) arg)->pre++; 169 170 if (rpc_g_initialized == true) 171 (*atfork_handler_ptr)(RPC_C_PREFORK); 172 173 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 174 ("(_pre_fork) returning, pid %d, pre %d, post_p %d, post_c %d\n", 175 ((struct atfork_user_data_t *) arg)->pid, 176 ((struct atfork_user_data_t *) arg)->pre, 177 ((struct atfork_user_data_t *) arg)->post_p, 178 ((struct atfork_user_data_t *) arg)->post_c)); 179} 180 181/* 182 * _ P O S T _ F O R K _ C H I L D 183 * 184 * This procedure is called in the child of a forked process immediately 185 * after the fork is performed. 186 */ 187 188INTERNAL void _post_fork_child 189( 190 dce_pointer_t arg 191) 192{ 193 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 194 ("(_post_fork_child) entering, pid %d, pre %d, post_p %d, post_c %d\n", 195 ((struct atfork_user_data_t *) arg)->pid, 196 ((struct atfork_user_data_t *) arg)->pre, 197 ((struct atfork_user_data_t *) arg)->post_p, 198 ((struct atfork_user_data_t *) arg)->post_c)); 199 200 ((struct atfork_user_data_t *) arg)->post_c++; 201 202 if (rpc_g_initialized == true) 203 (*atfork_handler_ptr)(RPC_C_POSTFORK_CHILD); 204 205 atfork_in_progress = false; 206 207 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 208 ("(_post_fork_child) returning, pid %d, pre %d, post_p %d, post_c %d\n", 209 ((struct atfork_user_data_t *) arg)->pid, 210 ((struct atfork_user_data_t *) arg)->pre, 211 ((struct atfork_user_data_t *) arg)->post_p, 212 ((struct atfork_user_data_t *) arg)->post_c)); 213} 214 215/* 216 * _ P O S T _ F O R K _ P A R E N T 217 * 218 * This procedure is called in the parent of a forked process immediately 219 * after the fork is performed. 220 */ 221 222INTERNAL void _post_fork_parent 223( 224 dce_pointer_t arg 225) 226{ 227 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 228 ("(_post_fork_parent) entering, pid %d, pre %d, post_p %d, post_c %d\n", 229 ((struct atfork_user_data_t *) arg)->pid, 230 ((struct atfork_user_data_t *) arg)->pre, 231 ((struct atfork_user_data_t *) arg)->post_p, 232 ((struct atfork_user_data_t *) arg)->post_c)); 233 234 ((struct atfork_user_data_t *) arg)->post_p++; 235 236 if (rpc_g_initialized == true) 237 (*atfork_handler_ptr)(RPC_C_POSTFORK_PARENT); 238 239 atfork_in_progress = false; 240 241 RPC_DBG_PRINTF(rpc_e_dbg_atfork, 1, 242 ("(_post_fork_parent) returning, pid %d, pre %d, post_p %d, post_c %d\n", 243 ((struct atfork_user_data_t *) arg)->pid, 244 ((struct atfork_user_data_t *) arg)->pre, 245 ((struct atfork_user_data_t *) arg)->post_p, 246 ((struct atfork_user_data_t *) arg)->post_c)); 247} 248 249PRIVATE void rpc__atfork 250( 251 void *handler 252) 253{ 254 if (handler == NULL) 255 return; 256 257 /* 258 * Don't register it again! 259 */ 260 if (atfork_handler_ptr != NULL) 261 return; 262 263 /* 264 * Save the address of the handler routine, and register our own 265 * handlers. (see note above) 266 */ 267 atfork_handler_ptr = (atfork_handler_ptr_t) handler; 268 rpc__atfork_user_data.pid = getpid(); 269 rpc__atfork_user_data.pre = 0; 270 rpc__atfork_user_data.post_p = 0; 271 rpc__atfork_user_data.post_c = 0; 272 273 dcethread_atfork_throw((dce_pointer_t)(&rpc__atfork_user_data), _pre_fork, 274 _post_fork_parent, _post_fork_child); 275} 276 277 278/* 279**++ 280** 281** ROUTINE NAME: rpc__fork_is_in_progress 282** 283** SCOPE: PRIVATE - declared in com.h 284** 285** DESCRIPTION: 286** 287** Return true iff the atfork handler is in progress. 288** 289** 290** INPUTS: none 291** 292** INPUTS/OUTPUTS: none 293** 294** OUTPUTS: none 295** 296** IMPLICIT INPUTS: none 297** 298** IMPLICIT OUTPUTS: none 299** 300** FUNCTION VALUE: boolean 301** 302** SIDE EFFECTS: none 303** 304**-- 305**/ 306 307PRIVATE boolean32 rpc__fork_is_in_progress (void) 308{ 309 /* 310 * We could lock, but there should be only one thread in fork-progress 311 * which can change it. 312 */ 313 return (atfork_in_progress); 314} 315 316#endif /* defined(ATFORK_SUPPORTED) */ 317