1c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes/* 2c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * Copyright (C) 2008 The Android Open Source Project 3c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * All rights reserved. 4c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * 5c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * Redistribution and use in source and binary forms, with or without 6c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * modification, are permitted provided that the following conditions 7c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * are met: 8c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * * Redistributions of source code must retain the above copyright 9c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * notice, this list of conditions and the following disclaimer. 10c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * * Redistributions in binary form must reproduce the above copyright 11c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * notice, this list of conditions and the following disclaimer in 12c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * the documentation and/or other materials provided with the 13c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * distribution. 14c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * 15c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes * SUCH DAMAGE. 27c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes */ 28c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 29c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes#include <errno.h> 30c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes#include <pthread.h> 31c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 32c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesstruct atfork_t { 33c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes atfork_t* next; 34c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes atfork_t* prev; 35c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 36c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes void (*prepare)(void); 37c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes void (*child)(void); 38c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes void (*parent)(void); 39c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes}; 40c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 41c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesstruct atfork_list_t { 42c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes atfork_t* first; 43c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes atfork_t* last; 44c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes}; 45c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 461728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic pthread_mutex_t g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; 471728b2396591853345507a063ed6075dfd251706Elliott Hughesstatic atfork_list_t g_atfork_list = { NULL, NULL }; 48c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 49c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesvoid __bionic_atfork_run_prepare() { 504b558f50a42c97d461f1dede5aaaae490ea99e2eElliott Hughes // We lock the atfork list here, unlock it in the parent, and reset it in the child. 51c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // This ensures that nobody can modify the handler array between the calls 52c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // to the prepare and parent/child handlers. 53c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // 544b558f50a42c97d461f1dede5aaaae490ea99e2eElliott Hughes // TODO: If a handler tries to mutate the list, they'll block. We should probably copy 554b558f50a42c97d461f1dede5aaaae490ea99e2eElliott Hughes // the list before forking, and have prepare, parent, and child all work on the consistent copy. 561728b2396591853345507a063ed6075dfd251706Elliott Hughes pthread_mutex_lock(&g_atfork_list_mutex); 57c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 58c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // Call pthread_atfork() prepare handlers. POSIX states that the prepare 59c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // handlers should be called in the reverse order of the parent/child 60c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // handlers, so we iterate backwards. 611728b2396591853345507a063ed6075dfd251706Elliott Hughes for (atfork_t* it = g_atfork_list.last; it != NULL; it = it->prev) { 62c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes if (it->prepare != NULL) { 63c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes it->prepare(); 64c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 65c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 66c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes} 67c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 68c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesvoid __bionic_atfork_run_child() { 691728b2396591853345507a063ed6075dfd251706Elliott Hughes for (atfork_t* it = g_atfork_list.first; it != NULL; it = it->next) { 70c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes if (it->child != NULL) { 71c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes it->child(); 72c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 73c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 74c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 751728b2396591853345507a063ed6075dfd251706Elliott Hughes g_atfork_list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; 76c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes} 77c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 78c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesvoid __bionic_atfork_run_parent() { 791728b2396591853345507a063ed6075dfd251706Elliott Hughes for (atfork_t* it = g_atfork_list.first; it != NULL; it = it->next) { 80c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes if (it->parent != NULL) { 81c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes it->parent(); 82c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 83c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 84c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 851728b2396591853345507a063ed6075dfd251706Elliott Hughes pthread_mutex_unlock(&g_atfork_list_mutex); 86c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes} 87c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 88c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughesint pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void)) { 89c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes atfork_t* entry = reinterpret_cast<atfork_t*>(malloc(sizeof(atfork_t))); 90c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes if (entry == NULL) { 91c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes return ENOMEM; 92c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 93c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 94c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes entry->prepare = prepare; 95c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes entry->parent = parent; 96c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes entry->child = child; 97c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 981728b2396591853345507a063ed6075dfd251706Elliott Hughes pthread_mutex_lock(&g_atfork_list_mutex); 99c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 100c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes // Append 'entry' to the list. 101c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes entry->next = NULL; 1021728b2396591853345507a063ed6075dfd251706Elliott Hughes entry->prev = g_atfork_list.last; 103c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes if (entry->prev != NULL) { 104c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes entry->prev->next = entry; 105c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 1061728b2396591853345507a063ed6075dfd251706Elliott Hughes if (g_atfork_list.first == NULL) { 1071728b2396591853345507a063ed6075dfd251706Elliott Hughes g_atfork_list.first = entry; 108c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes } 1091728b2396591853345507a063ed6075dfd251706Elliott Hughes g_atfork_list.last = entry; 110c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 1111728b2396591853345507a063ed6075dfd251706Elliott Hughes pthread_mutex_unlock(&g_atfork_list_mutex); 112c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes 113c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes return 0; 114c3f114037dbf028896310609fd28cf2b3da99c4dElliott Hughes} 115