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

Generated by: LCOV version 2.0-1