1a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov/* 2a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * Copyright (C) 2015 The Android Open Source Project 3a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * 4a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * Licensed under the Apache License, Version 2.0 (the "License"); 5a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * you may not use this file except in compliance with the License. 6a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * You may obtain a copy of the License at 7a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * 8a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * http://www.apache.org/licenses/LICENSE-2.0 9a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * 10a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * Unless required by applicable law or agreed to in writing, software 11a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * distributed under the License is distributed on an "AS IS" BASIS, 12a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * See the License for the specific language governing permissions and 14a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov * limitations under the License. 15a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov */ 16a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov#include <gtest/gtest.h> 17a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 18a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov#include <dlfcn.h> 19a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 2033697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes#include "utils.h" 2133697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes 22a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic int g_atfork_prepare_calls = 0; 23a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkPrepare1() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 1; } 24a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkPrepare2() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 2; } 25a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; } 26a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; } 27a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 28a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic int g_atfork_parent_calls = 0; 29a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkParent1() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 1; } 30a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkParent2() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 2; } 31a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; } 32a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; } 33a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 34a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic int g_atfork_child_calls = 0; 35a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 1; } 36a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 2; } 37a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; } 38a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanovstatic void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; } 39a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 40a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy IvanovTEST(pthread, pthread_atfork_with_dlclose) { 41a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1)); 42a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 43a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL); 44a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_TRUE(handle != nullptr) << dlerror(); 45a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void)); 46a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork")); 47a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_TRUE(fn != nullptr) << dlerror(); 48a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov // the library registers 2 additional atfork handlers in a constructor 49a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2)); 50a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3)); 51a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 52a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4)); 53a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 5433697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes pid_t pid = fork(); 55a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 56a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_NE(-1, pid) << strerror(errno); 57a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 58a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov if (pid == 0) { 59a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(1234, g_atfork_child_calls); 60a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov _exit(0); 61a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov } 62a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 63a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(1234, g_atfork_parent_calls); 64a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(4321, g_atfork_prepare_calls); 65a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 66a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov EXPECT_EQ(0, dlclose(handle)); 67a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0; 68a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 6933697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes AssertChildExited(pid, 0); 70a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 71a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov pid = fork(); 72a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 73a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_NE(-1, pid) << strerror(errno); 74a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 75a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov if (pid == 0) { 76a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(14, g_atfork_child_calls); 77a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov _exit(0); 78a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov } 79a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 80a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(14, g_atfork_parent_calls); 81a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov ASSERT_EQ(41, g_atfork_prepare_calls); 82a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov 8333697a0c43c48e15c3bcf018138b9b837d0099cdElliott Hughes AssertChildExited(pid, 0); 84a60fd09e2692e17c8bfa210d3cb64b490aea4c9dDmitriy Ivanov} 85