LCOV - code coverage report
Current view: top level - atrace/utrace/stacktrace - stacktrace_monitor.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.4 % 65 62
Test Date: 2026-08-31 10:07:06 Functions: 83.3 % 12 10

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : #include "stacktrace_monitor.h"
      11              : #include "stacktrace_unwind.h"
      12              : #include "adiag_print.h"
      13              : #include "mmpa_api.h"
      14              : typedef void (*ThreadAtFork)(void);
      15              : 
      16              : #define STACKTRACE_SLEEP_PERIOD 100000U // 100ms
      17              : #define STACKTRACE_UPDATE_PERIOD 100U   // 0.1s * 100 = 10s
      18              : #define STACKTRACE_THREAD_STACK_SIZE 128 * 1024
      19              : #define THREAD_STATUS_INIT 0
      20              : #define THREAD_STATUS_RUN 1
      21              : #define THREAD_STATUS_WAIT_EXIT 2
      22              : 
      23              : #define STACKTRACE_UPDATE_STATUS_INIT 0U
      24              : #define STACKTRACE_UPDATE_STATUS_START 1U
      25              : #define STACKTRACE_UPDATE_STATUS_FINISH 2U
      26              : 
      27              : static int32_t g_stacktraceMonitorThreadStatus = THREAD_STATUS_INIT;
      28              : 
      29              : static mmThread g_stacktraceMonitorPthreadId = 0;
      30              : static pid_t g_stacktraceMonitorthreadId = 0;
      31              : static uint32_t g_stacktraceUpdateStatus;
      32              : static bool g_forking = false;
      33              : STATIC pthread_mutex_t g_forkMutex = PTHREAD_MUTEX_INITIALIZER;
      34              : 
      35           88 : void StacktraceMonitorStartUpdate(void) { g_stacktraceUpdateStatus = STACKTRACE_UPDATE_STATUS_START; }
      36              : 
      37            0 : pid_t StacktraceMonitorGetTid(void) { return g_stacktraceMonitorthreadId; }
      38              : 
      39            0 : bool StacktraceCheckUpdateFinished(void) { return (g_stacktraceUpdateStatus == STACKTRACE_UPDATE_STATUS_FINISH); }
      40              : 
      41         1010 : static void* StacktraceMonitorProcess(void* arg)
      42              : {
      43              :     (void)arg;
      44         1010 :     g_stacktraceMonitorthreadId = (pid_t)syscall(SYS_gettid);
      45         1010 :     (void)mmSetCurrentThreadName("AtraceMonitor");
      46         3029 :     while (g_stacktraceMonitorThreadStatus == THREAD_STATUS_RUN) {
      47         1034 :         (void)usleep(STACKTRACE_SLEEP_PERIOD);
      48         1009 :         if (g_stacktraceUpdateStatus == STACKTRACE_UPDATE_STATUS_START) {
      49              :             // ensure dl_iterate_phdr is not being called when fork
      50           63 :             (void)pthread_mutex_lock(&g_forkMutex);
      51           63 :             TraceStackUnwindInit();
      52           63 :             (void)pthread_mutex_unlock(&g_forkMutex);
      53              : 
      54           63 :             g_stacktraceUpdateStatus = STACKTRACE_UPDATE_STATUS_FINISH;
      55              :         }
      56              :     }
      57          985 :     return NULL;
      58              : }
      59              : 
      60         1032 : static TraStatus StacktraceCreateMonitorThread(void)
      61              : {
      62              :     mmUserBlock_t thread;
      63         1032 :     thread.procFunc = StacktraceMonitorProcess;
      64         1032 :     thread.pulArg = NULL;
      65         1032 :     mmThreadAttr attr = {0, 0, 0, 0, 0, 0, STACKTRACE_THREAD_STACK_SIZE};
      66         1032 :     mmThread tid = 0;
      67         1032 :     if (mmCreateTaskWithThreadAttr(&tid, &thread, &attr) != 0) {
      68           22 :         ADIAG_ERR("create task failed, strerr=%s.", strerror(errno));
      69           22 :         return TRACE_FAILURE;
      70              :     }
      71         1010 :     g_stacktraceMonitorPthreadId = tid;
      72         1010 :     return TRACE_SUCCESS;
      73              : }
      74              : 
      75         1032 : static void StacktraceMonitorThreadInit(void)
      76              : {
      77         1032 :     g_stacktraceMonitorThreadStatus = THREAD_STATUS_RUN;
      78         1032 :     g_stacktraceUpdateStatus = STACKTRACE_UPDATE_STATUS_INIT;
      79         1032 :     TraStatus ret = StacktraceCreateMonitorThread();
      80         1032 :     if (ret != TRACE_SUCCESS) {
      81              :         // call unwind  in case thread creation fails
      82           22 :         g_stacktraceMonitorPthreadId = 0;
      83           22 :         ADIAG_ERR("Create monitor thread failed");
      84           22 :         return;
      85              :     }
      86              : }
      87              : 
      88          882 : static void StacktraceSubProcessInit(void)
      89              : {
      90          882 :     if (!g_forking) {
      91              :         // sub process has been initialized
      92          863 :         return;
      93              :     }
      94           19 :     (void)pthread_mutex_unlock(&g_forkMutex);
      95           19 :     g_stacktraceMonitorThreadStatus = THREAD_STATUS_WAIT_EXIT;
      96           19 :     StacktraceMonitorThreadInit();
      97           19 :     g_forking = false;
      98              : }
      99              : 
     100         9702 : STATIC void StacktraceProcessUnInit(void)
     101              : {
     102         9702 :     if (g_forking) {
     103         9493 :         return;
     104              :     }
     105          209 :     (void)pthread_mutex_lock(&g_forkMutex);
     106          209 :     g_forking = true; // set forking to true to avoid repeat uninit and init
     107              : }
     108              : 
     109         8820 : STATIC void StacktraceProcessInit(void)
     110              : {
     111         8820 :     g_forking = false;
     112         8820 :     (void)pthread_mutex_unlock(&g_forkMutex);
     113         8820 : }
     114              : 
     115         1013 : static void StacktracePrepareForFork(void)
     116              : {
     117         1013 :     int32_t ret = pthread_atfork(
     118              :         (ThreadAtFork)StacktraceProcessUnInit, (ThreadAtFork)StacktraceProcessInit,
     119              :         (ThreadAtFork)StacktraceSubProcessInit);
     120         1013 :     if (ret != 0) {
     121            0 :         ADIAG_WAR("can not call pthread_atfork, ret=%d", ret);
     122              :     }
     123         1013 : }
     124              : 
     125         1013 : void StacktraceMonitorInit(void)
     126              : {
     127         1013 :     StacktracePrepareForFork();
     128         1013 :     StacktraceMonitorThreadInit();
     129         1013 : }
     130              : 
     131         1069 : void StacktraceMonitorExit(void)
     132              : {
     133         1069 :     if (g_stacktraceMonitorThreadStatus != THREAD_STATUS_RUN) {
     134          102 :         return;
     135              :     }
     136          967 :     g_stacktraceMonitorThreadStatus = THREAD_STATUS_WAIT_EXIT;
     137          967 :     if (g_stacktraceMonitorPthreadId != 0) {
     138          945 :         (void)mmJoinTask(&g_stacktraceMonitorPthreadId);
     139          945 :         g_stacktraceMonitorPthreadId = 0;
     140          945 :         g_stacktraceMonitorthreadId = 0;
     141              :     }
     142              : }
        

Generated by: LCOV version 2.0-1