|
|
|
@ -1,3 +1,4 @@
|
|
|
|
|
// 版权声明
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
|
|
|
|
|
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
|
|
|
|
@ -28,27 +29,35 @@
|
|
|
|
|
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
|
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
// 包含头文件
|
|
|
|
|
#include "it_pthread_test.h"
|
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
|
|
// 声明外部函数nanosleep,用于线程休眠
|
|
|
|
|
extern int nanosleep(const struct timespec *req, struct timespec *rem);
|
|
|
|
|
|
|
|
|
|
// 定义全局互斥锁和测试变量
|
|
|
|
|
static pthread_mutex_t g_mux = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
static volatile int g_testAtforkCount = 0;
|
|
|
|
|
static int g_testAtforkPrepare = 0;
|
|
|
|
|
static int g_testAtforkParent = 0;
|
|
|
|
|
|
|
|
|
|
// 线程函数Doit,用于测试pthread_atfork
|
|
|
|
|
static void *Doit(void *arg)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
struct timespec ts = { 2, 0 }; // 2, set time 2s.
|
|
|
|
|
struct timespec ts = { 2, 0 }; // 设置休眠时间为2秒
|
|
|
|
|
|
|
|
|
|
// 断言g_testAtforkCount为1
|
|
|
|
|
ICUNIT_GOTO_EQUAL(g_testAtforkCount, 1, g_testAtforkCount, EXIT);
|
|
|
|
|
|
|
|
|
|
// 尝试获取互斥锁
|
|
|
|
|
err = pthread_mutex_lock(&g_mux);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
|
|
|
|
|
// 休眠2秒
|
|
|
|
|
(void)nanosleep(&ts, NULL);
|
|
|
|
|
// 释放互斥锁
|
|
|
|
|
err = pthread_mutex_unlock(&g_mux);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
|
|
|
|
@ -56,17 +65,22 @@ EXIT:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 线程函数Doit1,与Doit类似,用于测试pthread_atfork
|
|
|
|
|
static void *Doit1(void *arg)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
struct timespec ts = { 2, 0 }; // 2, set time 2s.
|
|
|
|
|
struct timespec ts = { 2, 0 }; // 设置休眠时间为2秒
|
|
|
|
|
|
|
|
|
|
// 断言g_testAtforkCount为1
|
|
|
|
|
ICUNIT_GOTO_EQUAL(g_testAtforkCount, 1, g_testAtforkCount, EXIT);
|
|
|
|
|
|
|
|
|
|
// 尝试获取互斥锁
|
|
|
|
|
err = pthread_mutex_lock(&g_mux);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
|
|
|
|
|
// 休眠2秒
|
|
|
|
|
(void)nanosleep(&ts, NULL);
|
|
|
|
|
// 释放互斥锁
|
|
|
|
|
err = pthread_mutex_unlock(&g_mux);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
|
|
|
|
@ -74,15 +88,19 @@ EXIT:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Prepare函数,在fork之前调用
|
|
|
|
|
static void Prepare(void)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
|
|
|
|
|
// 释放互斥锁
|
|
|
|
|
err = pthread_mutex_unlock(&g_mux);
|
|
|
|
|
ICUNIT_ASSERT_EQUAL_VOID(err, 0, err);
|
|
|
|
|
// 增加Prepare函数的调用次数
|
|
|
|
|
g_testAtforkPrepare++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parent函数,在fork之后在父进程中调用
|
|
|
|
|
static void Parent(void)
|
|
|
|
|
{
|
|
|
|
|
int err = pthread_mutex_lock(&g_mux);
|
|
|
|
@ -90,79 +108,56 @@ static void Parent(void)
|
|
|
|
|
g_testAtforkParent++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 测试pthread_atfork的函数
|
|
|
|
|
static void *PthreadAtforkTest(void *arg)
|
|
|
|
|
{
|
|
|
|
|
int err, ret;
|
|
|
|
|
int pid;
|
|
|
|
|
int status = 0;
|
|
|
|
|
struct timespec ts = { 1, 0 };
|
|
|
|
|
struct timespec ts = { 1, 0 }; // 设置休眠时间为1秒
|
|
|
|
|
pthread_t tid;
|
|
|
|
|
|
|
|
|
|
// 初始化测试变量
|
|
|
|
|
g_testAtforkCount = 0;
|
|
|
|
|
g_testAtforkPrepare = 0;
|
|
|
|
|
g_testAtforkParent = 0;
|
|
|
|
|
|
|
|
|
|
// 设置fork时的回调函数
|
|
|
|
|
err = pthread_atfork(Prepare, Parent, NULL);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
// 增加fork调用次数
|
|
|
|
|
g_testAtforkCount++;
|
|
|
|
|
// 创建线程Doit
|
|
|
|
|
err = pthread_create(&tid, NULL, Doit, NULL);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT);
|
|
|
|
|
|
|
|
|
|
// 休眠1秒
|
|
|
|
|
nanosleep(&ts, NULL);
|
|
|
|
|
// 执行fork
|
|
|
|
|
pid = fork();
|
|
|
|
|
ICUNIT_GOTO_EQUAL(g_testAtforkPrepare, 1, g_testAtforkPrepare, EXIT);
|
|
|
|
|
if (pid == 0) {
|
|
|
|
|
// 子进程中执行Doit1
|
|
|
|
|
Doit1(NULL);
|
|
|
|
|
exit(10); // 10, set exit status.
|
|
|
|
|
// 设置退出状态
|
|
|
|
|
exit(10); // 设置退出状态为10
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT_WAIT); // 100000, The pid will never exceed 100000.
|
|
|
|
|
// 父进程等待子进程结束
|
|
|
|
|
ICUNIT_GOTO_WITHIN_EQUAL(pid, 0, 100000, pid, EXIT_WAIT); // 确保pid不会超过100000
|
|
|
|
|
ICUNIT_GOTO_EQUAL(g_testAtforkParent, 1, g_testAtforkParent, EXIT_WAIT);
|
|
|
|
|
|
|
|
|
|
// 等待线程Doit结束
|
|
|
|
|
err = pthread_join(tid, NULL);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, 0, err, EXIT_WAIT);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 等待子进程结束并获取退出状态
|
|
|
|
|
err = waitpid(pid, &status, 0);
|
|
|
|
|
status = WEXITSTATUS(status);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(err, pid, err, EXIT);
|
|
|
|
|
ICUNIT_GOTO_EQUAL(status, 10, status, EXIT); // 10, get exit status.
|
|
|
|
|
ICUNIT_GOTO_EQUAL(status, 10, status, EXIT); // 获取子进程的退出状态
|
|
|
|
|
|
|
|
|
|
EXIT:
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
EXIT_WAIT:
|
|
|
|
|
(void)waitpid(pid, 0, 0);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int Testcase(void)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
pthread_t newPthread;
|
|
|
|
|
int curThreadPri, curThreadPolicy;
|
|
|
|
|
pthread_attr_t a = { 0 };
|
|
|
|
|
struct sched_param param = { 0 };
|
|
|
|
|
|
|
|
|
|
ret = pthread_getschedparam(pthread_self(), &curThreadPolicy, ¶m);
|
|
|
|
|
ICUNIT_ASSERT_EQUAL(ret, 0, -ret);
|
|
|
|
|
|
|
|
|
|
curThreadPri = param.sched_priority;
|
|
|
|
|
|
|
|
|
|
ret = pthread_attr_init(&a);
|
|
|
|
|
pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
|
|
|
|
|
param.sched_priority = curThreadPri + 2; // 2, adjust the priority.
|
|
|
|
|
pthread_attr_setschedparam(&a, ¶m);
|
|
|
|
|
ret = pthread_create(&newPthread, &a, PthreadAtforkTest, 0);
|
|
|
|
|
ICUNIT_ASSERT_EQUAL(ret, 0, ret);
|
|
|
|
|
|
|
|
|
|
ret = pthread_join(newPthread, NULL);
|
|
|
|
|
ICUNIT_ASSERT_EQUAL(ret, 0, ret);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ItTestPthreadAtfork002(void)
|
|
|
|
|
{
|
|
|
|
|
TEST_ADD_CASE("IT_PTHREAD_ATFORK_002", Testcase, TEST_POSIX, TEST_MEM, TEST_LEVEL0, TEST_FUNCTION);
|
|
|
|
|
}
|
|
|
|
|
EXIT
|