Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1-only */
2 : /**
3 : * @file nnstreamer_log.c
4 : * @date 31 Mar 2022
5 : * @brief Internal log and error handling for NNStreamer plugins and core codes.
6 : * @see http://github.com/nnstreamer/nnstreamer
7 : * @author MyungJoo Ham <myungjoo.ham@samsung.com>
8 : * @bug No known bugs except for NYI items
9 : */
10 :
11 : #ifdef __ANDROID__
12 : #ifndef _NO_EXECINFO_
13 : #define _NO_EXECINFO_
14 : #endif
15 : #endif
16 :
17 : #ifndef _NO_EXECINFO_
18 : /* Android does not have execinfo.h. It has unwind.h instead. */
19 : #include <execinfo.h>
20 : #endif
21 :
22 : #include <stdlib.h>
23 : #include <string.h>
24 : #include <stdio.h>
25 : #include <glib.h>
26 :
27 : #include "nnstreamer_log.h"
28 :
29 : /**
30 : * @brief stack trace as a string for error messages
31 : * @return a string of stacktrace result. caller should free it.
32 : * @todo The .c file location of this function might be not appropriate.
33 : */
34 : char *
35 81 : _backtrace_to_string (void)
36 : {
37 81 : char *retstr = NULL;
38 : #ifndef _NO_EXECINFO_
39 : void *array[20];
40 : char **strings;
41 : int size, i, len;
42 81 : int strsize = 0, strcursor = 0;
43 :
44 81 : size = backtrace (array, 20);
45 81 : strings = backtrace_symbols (array, size);
46 81 : if (strings != NULL) {
47 1701 : for (i = 0; i < size; i++)
48 1620 : strsize += strlen (strings[i]);
49 :
50 81 : retstr = malloc (sizeof (char) * (strsize + 1));
51 81 : if (retstr) {
52 1701 : for (i = 0; i < size; i++) {
53 1620 : len = strlen (strings[i]);
54 1620 : memcpy (retstr + strcursor, strings[i], len);
55 1620 : strcursor += len;
56 : }
57 :
58 81 : retstr[strsize] = '\0';
59 : }
60 :
61 81 : free (strings);
62 : }
63 : #else
64 : retstr = strdup ("Android-nnstreamer does not support backtrace.\n");
65 : #endif
66 :
67 81 : return retstr;
68 : }
69 :
70 : #define _NNSTREAMER_ERROR_LENGTH (4096U)
71 : static char errmsg[_NNSTREAMER_ERROR_LENGTH] = { 0 };
72 :
73 : static int errmsg_reported = 0;
74 : G_LOCK_DEFINE_STATIC (errlock);
75 :
76 : /**
77 : * @brief return the last internal error string and clean it.
78 : * @return a string of error. Do not free the returned string.
79 : */
80 : const char *
81 0 : _nnstreamer_error (void)
82 : {
83 0 : G_LOCK (errlock);
84 0 : if (errmsg_reported || errmsg[0] == '\0') {
85 0 : G_UNLOCK (errlock);
86 0 : return NULL;
87 : }
88 0 : G_UNLOCK (errlock);
89 :
90 0 : errmsg_reported = 1;
91 0 : return errmsg;
92 : }
93 :
94 : /**
95 : * @brief overwrites the error message buffer with the new message.
96 : */
97 : __attribute__((__format__ (__printf__, 1, 2)))
98 14386 : void _nnstreamer_error_write (const char *fmt, ...)
99 : {
100 : /**
101 : * The attribute is for clang workaround in macos:
102 : * https://stackoverflow.com/questions/20167124/vsprintf-and-vsnprintf-wformat-nonliteral-warning-on-clang-5-0
103 : */
104 : va_list arg_ptr;
105 14386 : G_LOCK (errlock);
106 :
107 14386 : va_start (arg_ptr, fmt);
108 14386 : vsnprintf (errmsg, _NNSTREAMER_ERROR_LENGTH, fmt, arg_ptr);
109 14386 : va_end (arg_ptr);
110 :
111 14386 : errmsg_reported = 0;
112 :
113 14386 : G_UNLOCK (errlock);
114 14386 : }
115 :
116 : /**
117 : * @brief cleans up the error message buffer.
118 : */
119 : void
120 0 : _nnstreamer_error_clean (void)
121 : {
122 0 : G_LOCK (errlock);
123 :
124 0 : errmsg[0] = '\0';
125 :
126 0 : G_UNLOCK (errlock);
127 0 : }
|