LCOV - code coverage report
Current view: top level - atrace/trace_server/utrace_server - trace_server_socket.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.8 % 148 124
Test Date: 2026-07-28 10:53:44 Functions: 100.0 % 8 8

            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              : 
      11              : #include "trace_server_socket.h"
      12              : #include "grp.h"
      13              : #include "adiag_utils.h"
      14              : #include "adiag_print.h"
      15              : #include "trace_system_api.h"
      16              : #include "trace_session_mgr.h"
      17              : #include "trace_node.h"
      18              : #include "trace_msg.h"
      19              : 
      20              : #define SIZE_SIXTEEN_MB         (16 * 1024 * 1024) // 16MB
      21              : #define SOCKET_TIME_INTERVAL    10000 // 10ms
      22              : #define SOCKET_MAX_DATA_SIZE    524288U
      23              : #ifndef TRACE_SERVER_USER_NAME
      24              : #define TRACE_SERVER_USER_NAME  "HwHiAiUser"
      25              : #endif
      26              : 
      27              : STATIC int32_t g_sockFd = -1;
      28              : STATIC char g_socketPath[SOCKET_PATH_MAX_LENGTH] = { 0 };
      29              : STATIC TraceThread g_traceSocketThread = 0;
      30              : STATIC bool g_traceSocketThreadState = false;
      31              : 
      32           16 : STATIC int32_t TraceGetSocketPath(int32_t devId, char *socketPath, uint32_t len)
      33              : {
      34           16 :     if (devId == -1) {
      35           12 :         int32_t ret = sprintf_s(socketPath, len, "%s%s", SOCKET_FILE_DIR, SOCKET_FILE);
      36           12 :         if (ret == -1) {
      37            2 :             ADIAG_ERR("snprintf_s socket path failed, strerr=%s, pid=%d.", strerror(AdiagGetErrorCode()), getpid());
      38            2 :             return TRACE_FAILURE;
      39              :         }
      40              :     } else {
      41            4 :         int32_t ret = sprintf_s(socketPath, len, "%s%s_%d", SOCKET_FILE_DIR, SOCKET_FILE, devId);
      42            4 :         if (ret == -1) {
      43            2 :             ADIAG_ERR("snprintf_s socket path failed, strerr=%s, pid=%d, vfid=%u.",
      44              :                 strerror(AdiagGetErrorCode()), getpid(), devId);
      45            2 :             return TRACE_FAILURE;
      46              :         }
      47              :     }
      48           12 :     return TRACE_SUCCESS;
      49              : }
      50              : 
      51           12 : STATIC int32_t TraceCreateSocketByFile(char *socketPath, const char *groupName, uint32_t permission)
      52              : {
      53              :     struct sockaddr_un addr;
      54           12 :     int32_t nSendBuf = SIZE_SIXTEEN_MB;
      55           12 :     (void)memset_s(&addr, sizeof(addr), 0, sizeof(addr));
      56           12 :     addr.sun_family = AF_UNIX;
      57              : 
      58           12 :     errno_t err = strcpy_s(addr.sun_path, sizeof(addr.sun_path), socketPath);
      59           12 :     ADIAG_CHK_EXPR_ACTION(err != EOK, return -1,
      60              :         "strcpy_s failed, result=%d, strerr=%s.", (int32_t)err, strerror(AdiagGetErrorCode()));
      61              : 
      62              :     // Unlink the previous socket file first.
      63           12 :     int32_t ret = unlink(addr.sun_path);
      64           12 :     if (ret != 0) {
      65            9 :         ADIAG_WAR("can not unlink file=%s, strerr=%s.", addr.sun_path, strerror(AdiagGetErrorCode()));
      66              :     }
      67              : 
      68              :     // Create socket.
      69           12 :     int32_t sockFd = TraceSocket(AF_UNIX, SOCK_DGRAM, 0);
      70           12 :     ADIAG_CHK_EXPR_ACTION(sockFd < 0, return -1,
      71              :         "create socket failed, strerr=%s.", strerror(AdiagGetErrorCode()));
      72              : 
      73              :     do {
      74              :         // Set socket description.
      75           12 :         ret = setsockopt(sockFd, SOL_SOCKET, SO_RCVBUF, (const char *)&nSendBuf, sizeof(int32_t));
      76           12 :         if (ret < 0) {
      77            1 :             ADIAG_ERR("set socket option failed, strerr=%s.", strerror(AdiagGetErrorCode()));
      78            1 :             break;
      79              :         }
      80              : 
      81              :         // bind socket with a certain address.
      82           11 :         ret = TraceBind(sockFd, (TraceSockAddr *)&addr, sizeof(addr));
      83           11 :         if (ret != TRACE_SUCCESS) {
      84            1 :             ADIAG_ERR("bind socket failed, bind path is: %s, strerr=%s.", addr.sun_path, strerror(AdiagGetErrorCode()));
      85            1 :             break;
      86              :         }
      87              : 
      88              :         // Get the GID by using group name string
      89           10 :         struct group *grpInfo = getgrnam(groupName);
      90           10 :         if (grpInfo == NULL) {
      91            0 :             ADIAG_ERR("%s does not exist", groupName);
      92            0 :             break;
      93              :         }
      94              : 
      95              :         // Change the socket files owner and group.
      96           10 :         ret = lchown(addr.sun_path, getuid(), grpInfo->gr_gid);
      97           10 :         if (ret != TRACE_SUCCESS) {
      98            0 :             ADIAG_ERR("change the socket file: %s group failed, strerr=%s.",
      99              :                 addr.sun_path, strerror(AdiagGetErrorCode()));
     100            0 :             break;
     101              :         }
     102              : 
     103              :         // Set the socket files permission.
     104           10 :         ret = TraceChmod(addr.sun_path, permission);
     105           10 :         if (ret != TRACE_SUCCESS) {
     106            1 :             ADIAG_ERR("chmod %s failed , strerr=%s.", addr.sun_path, strerror(AdiagGetErrorCode()));
     107            1 :             break;
     108              :         }
     109              : 
     110            9 :         ADIAG_INF("create socket succeed, socket path: %s, fd %d.", addr.sun_path, sockFd);
     111            9 :         return sockFd;
     112              :     } while (true);
     113              : 
     114            3 :     TraceCloseSocket(sockFd);
     115            3 :     return -1;
     116              : }
     117              : 
     118            9 : STATIC TraStatus TraceServerMsgParse(UtraceMsg *traceMsg, TraceEventMsg *eventMsg)
     119              : {
     120            9 :     eventMsg->msgType = TRACE_EVENT_MSG;
     121            9 :     eventMsg->devId = traceMsg->deviceId;
     122            9 :     eventMsg->pid = (int32_t)traceMsg->hostPid;
     123            9 :     eventMsg->seqFlag = TRACE_MSG_SEQFLAG_SINGLE;
     124            9 :     eventMsg->bufLen = traceMsg->dataLength;
     125            9 :     eventMsg->saveType = traceMsg->saveType;
     126            9 :     errno_t err = memcpy_s(eventMsg->buf, traceMsg->dataLength, traceMsg + 1U, traceMsg->dataLength);
     127            9 :     if (err != EOK) {
     128            0 :         ADIAG_ERR("memcpy failed, length = %u bytes, err = %d, strerr = %s.",
     129              :             traceMsg->dataLength, (int32_t)err, strerror(AdiagGetErrorCode()));
     130            0 :         return TRACE_FAILURE;
     131              :     }
     132            9 :     err = strcpy_s(eventMsg->eventName, EVENT_NAME_MAX_LENGTH, traceMsg->objName);
     133            9 :     if (err != EOK) {
     134            0 :         ADIAG_ERR("strcpy_s failed, err = %d, strerr = %s.", (int32_t)err, strerror(AdiagGetErrorCode()));
     135            0 :         return TRACE_FAILURE;
     136              :     }
     137            9 :     err = strcpy_s(eventMsg->eventTime, TIMESTAMP_MAX_LENGTH, traceMsg->eventTime);
     138            9 :     if (err != EOK) {
     139            0 :         ADIAG_ERR("strcpy_s failed, err = %d, strerr = %s.", (int32_t)err, strerror(AdiagGetErrorCode()));
     140            0 :         return TRACE_FAILURE;
     141              :     }
     142            9 :     return TRACE_SUCCESS;
     143              : }
     144              : 
     145            9 : STATIC void TraceServerDataProcess(char *recvBuf, uint32_t len)
     146              : {
     147            9 :     if (len < sizeof(UtraceMsg)) {
     148            0 :         ADIAG_ERR("parse data received from utrace failed, data length(%u bytes) less then min length(%zu bytes).",
     149              :             len, sizeof(UtraceMsg));
     150            0 :         return;
     151              :     }
     152            9 :     UtraceMsg *traceMsg = (UtraceMsg *)recvBuf;
     153            9 :     ADIAG_CHK_EXPR_ACTION(traceMsg->magic != UTRACE_HEAD_MAGIC, return,
     154              :         "check magic of data from utrace failed, expect magic = %hu, current magic = %hu.",
     155              :         UTRACE_HEAD_MAGIC, traceMsg->magic);
     156            9 :     ADIAG_CHK_EXPR_ACTION(traceMsg->version < UTRACE_HEAD_VERSION, return,
     157              :         "check version of data from utrace failed, expect version = %hu, current version = %hu.",
     158              :         UTRACE_HEAD_VERSION, traceMsg->version);
     159            9 :     ADIAG_CHK_EXPR_ACTION((traceMsg->dataLength == 0) || (traceMsg->dataLength > len), return,
     160              :         "data length[%u] is out of range[0-%u].", traceMsg->dataLength, len);
     161              : 
     162            9 :     TraceEventMsg *eventMsg = (TraceEventMsg *)AdiagMalloc(sizeof(TraceEventMsg) + traceMsg->dataLength);
     163            9 :     if (eventMsg == NULL) {
     164            0 :         ADIAG_ERR("malloc for event msg failed, strerr = %s.", strerror(AdiagGetErrorCode()));
     165            0 :         return;
     166              :     }
     167            9 :     if (TraceServerMsgParse(traceMsg, eventMsg) != TRACE_SUCCESS) {
     168            0 :         ADIAG_ERR("parse msg from socket failed, pid = %u.", traceMsg->hostPid);
     169            0 :         ADIAG_SAFE_FREE(eventMsg);
     170            0 :         return;
     171              :     }
     172            9 :     TraceServerSessionLock();
     173            9 :     SessionNode *sessionNode = TraceServerGetSessionNode((int32_t)traceMsg->hostPid, (int32_t)traceMsg->deviceId);
     174            9 :     if (sessionNode == NULL) {
     175            5 :         ADIAG_WAR("no session node is valid, pid = %u.", traceMsg->hostPid);
     176            5 :         TraceServerSessionUnlock();
     177            5 :         ADIAG_SAFE_FREE(eventMsg);
     178            5 :         return;
     179              :     }
     180            4 :     TraStatus ret = TraceTsPushNode(sessionNode, eventMsg->seqFlag,
     181            4 :         (void *)eventMsg, eventMsg->bufLen + sizeof(TraceEventMsg));
     182            4 :     TraceServerSessionUnlock();
     183            4 :     if (ret != TRACE_SUCCESS) {
     184            0 :         ADIAG_ERR("push node failed, ret = %d, pid = %u.", ret, eventMsg->pid);
     185            0 :         ADIAG_SAFE_FREE(eventMsg);
     186            0 :         return;
     187              :     }
     188            4 :     ADIAG_DBG("log read by socket successfully, eventMsg: msgType=%u, eventType=%u, seqFlag=%u,"
     189              :         "devId=%u, pid=%d, eventName=%s, eventTime=%s, saveType=%u, bufLen=%u bytes.",
     190              :         (uint32_t)eventMsg->msgType, (uint32_t)eventMsg->eventType, (uint32_t)eventMsg->seqFlag, eventMsg->devId,
     191              :         eventMsg->pid, eventMsg->eventName, eventMsg->eventTime, (uint32_t)eventMsg->saveType, eventMsg->bufLen);
     192              : }
     193              : 
     194            8 : STATIC void *TraceServerSocketRecv(void *arg)
     195              : {
     196              :     (void)arg;
     197            8 :     ADIAG_RUN_INF("trace server socket thread start, socket path = %s.", g_socketPath);
     198            8 :     if (TraceSetThreadName("TraceServerSocketRecv") != TRACE_SUCCESS) {
     199            2 :         ADIAG_WAR("can not set thread name(TraceServerSocketRecv) but continue.");
     200              :     }
     201              : 
     202            8 :     size_t recvBufLen = SOCKET_MAX_DATA_SIZE; // max receive size
     203            8 :     char *recvBuf = (char *)AdiagMalloc(recvBufLen);
     204            8 :     if (recvBuf == NULL) {
     205            0 :         ADIAG_ERR("create receive buffer failed.");
     206            0 :         return NULL;
     207              :     }
     208           17 :     while (g_traceSocketThreadState) {
     209           12 :         (void)memset_s(recvBuf, recvBufLen, 0, recvBufLen);
     210           12 :         ssize_t len = read(g_sockFd, recvBuf, recvBufLen);
     211            9 :         if (len <= 0) {
     212            0 :             usleep(SOCKET_TIME_INTERVAL);
     213            0 :             continue;
     214              :         }
     215            9 :         TraceServerDataProcess(recvBuf, (uint32_t)len);
     216              :     }
     217            5 :     ADIAG_SAFE_FREE(recvBuf);
     218            5 :     TraceCloseSocket(g_sockFd);
     219            5 :     g_sockFd = -1;
     220            5 :     (void)unlink(g_socketPath);
     221            5 :     ADIAG_RUN_INF("thread TraceServerSocketRecv exit.");
     222            5 :     return NULL;
     223              : }
     224              : 
     225            9 : STATIC TraStatus TraceServerCreateSocketRecvThread(void)
     226              : {
     227              :     TraceUserBlock thread;
     228            9 :     thread.procFunc = TraceServerSocketRecv;
     229            9 :     thread.pulArg = NULL;
     230            9 :     TraceThreadAttr attr = { 1, 0, 0, 0, 0, 0, TRACE_THREAD_STACK_SIZE };
     231            9 :     TraceThread tid = 0;
     232            9 :     g_traceSocketThreadState = true;
     233            9 :     if (TraceCreateTaskWithThreadAttr(&tid, &thread, &attr) != TRACE_SUCCESS) {
     234            1 :         ADIAG_ERR("create trace server socket receive thread failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     235            1 :         return TRACE_FAILURE;
     236              :     }
     237            8 :     g_traceSocketThread = tid;
     238            8 :     ADIAG_RUN_INF("create trace server socket receive thread successfully, tid = %d.", (int32_t)g_traceSocketThread);
     239            8 :     return TRACE_SUCCESS;
     240              : }
     241              : 
     242           16 : TraStatus TraceServerCreateSocketRecv(int32_t devId)
     243              : {
     244           16 :     TraStatus ret = TraceGetSocketPath(devId, g_socketPath, SOCKET_PATH_MAX_LENGTH);
     245           16 :     ADIAG_CHK_EXPR_ACTION(ret != TRACE_SUCCESS, return TRACE_FAILURE, "get trace socket path failed, result=%d.", ret);
     246              : 
     247           12 :     ADIAG_INF("socket path is: %s.", g_socketPath);
     248           12 :     g_sockFd = TraceCreateSocketByFile(g_socketPath, TRACE_SERVER_USER_NAME, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
     249           12 :     ADIAG_CHK_EXPR_ACTION(g_sockFd == TRACE_FAILURE, return TRACE_FAILURE,
     250              :         "create socket failed, strerr=%s.", strerror(AdiagGetErrorCode()));
     251              :     // start thread
     252            9 :     ret = TraceServerCreateSocketRecvThread();
     253            9 :     if (ret != TRACE_SUCCESS) {
     254            1 :         ADIAG_ERR("create socket receive thread failed.");
     255            1 :         TraceCloseSocket(g_sockFd);
     256            1 :         g_sockFd = -1;
     257            1 :         (void)unlink(g_socketPath);
     258            1 :         return TRACE_FAILURE;
     259              :     }
     260            8 :     return TRACE_SUCCESS;
     261              : }
     262              : 
     263           28 : void TraceServerDestroySocketRecv(void)
     264              : {
     265           28 :     g_traceSocketThreadState = false;
     266           28 : }
        

Generated by: LCOV version 2.0-1