xref: /aosp_15_r20/external/deqp/framework/qphelper/qpDebugOut.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Helper Library
3  * -------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Debug output utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "qpDebugOut.h"
25 
26 #include "qpCrashHandler.h" /*!< for QP_USE_SIGNAL_HANDLER */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 typedef enum MessageType_e
32 {
33     MESSAGETYPE_INFO = 0,
34     MESSAGETYPE_ERROR,
35     MESSAGETYPE_NONFATAL_ERROR,
36 
37     MESSAGETYPE_LAST
38 } MessageType;
39 
40 static writePtr writeRedirect       = 0;
41 static writeFtmPtr writeFtmRedirect = 0;
42 
43 static void printRaw(MessageType type, const char *msg);
44 static void printFmt(MessageType type, const char *fmt, va_list args);
45 static void exitProcess(void);
46 
qpRedirectOut(writePtr w,writeFtmPtr wftm)47 void qpRedirectOut(writePtr w, writeFtmPtr wftm)
48 {
49     writeRedirect    = w;
50     writeFtmRedirect = wftm;
51 }
52 
qpPrint(const char * message)53 void qpPrint(const char *message)
54 {
55     printRaw(MESSAGETYPE_INFO, message);
56 }
57 
qpPrintf(const char * format,...)58 void qpPrintf(const char *format, ...)
59 {
60     va_list args;
61     va_start(args, format);
62     printFmt(MESSAGETYPE_INFO, format, args);
63     va_end(args);
64 }
65 
qpPrintErrorf(const char * format,...)66 void qpPrintErrorf(const char *format, ...)
67 {
68     va_list args;
69     va_start(args, format);
70     printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
71     va_end(args);
72 }
73 
qpPrintv(const char * format,va_list args)74 void qpPrintv(const char *format, va_list args)
75 {
76     printFmt(MESSAGETYPE_INFO, format, args);
77 }
78 
qpPrintErrorv(const char * format,va_list args)79 void qpPrintErrorv(const char *format, va_list args)
80 {
81     printFmt(MESSAGETYPE_NONFATAL_ERROR, format, args);
82 }
83 
qpDief(const char * format,...)84 void qpDief(const char *format, ...)
85 {
86     va_list args;
87     va_start(args, format);
88     printFmt(MESSAGETYPE_ERROR, format, args);
89     va_end(args);
90 
91     exitProcess();
92 }
93 
qpDiev(const char * format,va_list args)94 void qpDiev(const char *format, va_list args)
95 {
96     printFmt(MESSAGETYPE_ERROR, format, args);
97     exitProcess();
98 }
99 
100 /* print() implementation. */
101 #if (DE_OS == DE_OS_ANDROID)
102 
103 #include <android/log.h>
104 
getLogPriority(MessageType type)105 static android_LogPriority getLogPriority(MessageType type)
106 {
107     switch (type)
108     {
109     case MESSAGETYPE_INFO:
110         return ANDROID_LOG_INFO;
111     case MESSAGETYPE_ERROR:
112         return ANDROID_LOG_FATAL;
113     default:
114         return ANDROID_LOG_DEBUG;
115     }
116 }
117 
printRaw(MessageType type,const char * message)118 void printRaw(MessageType type, const char *message)
119 {
120     if (writeRedirect && !writeRedirect(type, message))
121         return;
122 
123     __android_log_write(getLogPriority(type), "dEQP", message);
124 }
125 
printFmt(MessageType type,const char * format,va_list args)126 void printFmt(MessageType type, const char *format, va_list args)
127 {
128     if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
129         return;
130 
131     __android_log_vprint(getLogPriority(type), "dEQP", format, args);
132 }
133 
134 #else
135 
getOutFile(MessageType type)136 static FILE *getOutFile(MessageType type)
137 {
138     if (type == MESSAGETYPE_ERROR || type == MESSAGETYPE_NONFATAL_ERROR)
139         return stderr;
140     else
141         return stdout;
142 }
143 
printRaw(MessageType type,const char * message)144 void printRaw(MessageType type, const char *message)
145 {
146     if (writeRedirect && !writeRedirect(type, message))
147         return;
148 
149     FILE *out = getOutFile(type);
150 
151     if (type == MESSAGETYPE_ERROR)
152         fprintf(out, "FATAL ERROR: ");
153 
154     fputs(message, out);
155 
156     if (type == MESSAGETYPE_ERROR)
157     {
158         putc('\n', out);
159         fflush(out);
160     }
161 }
162 
printFmt(MessageType type,const char * format,va_list args)163 void printFmt(MessageType type, const char *format, va_list args)
164 {
165     if (writeFtmRedirect && !writeFtmRedirect(type, format, args))
166         return;
167 
168     FILE *out = getOutFile(type);
169 
170     if (type == MESSAGETYPE_ERROR)
171         fprintf(out, "FATAL ERROR: ");
172 
173     vfprintf(out, format, args);
174 
175     if (type == MESSAGETYPE_ERROR)
176     {
177         putc('\n', out);
178         fflush(out);
179     }
180 }
181 
182 #endif
183 
184 /* exitProcess() implementation. */
185 #if (DE_OS == DE_OS_WIN32)
186 
187 #define NOMINMAX
188 #define VC_EXTRALEAN
189 #define WIN32_LEAN_AND_MEAN
190 #include <windows.h>
191 
exitProcess(void)192 static void exitProcess(void)
193 {
194     /* Some API implementations register atexit() functions that may hang.
195        By using TerminateProcess() we can avoid calling any potentially hanging exit routines. */
196     HANDLE curProc = GetCurrentProcess();
197     TerminateProcess(curProc, -1);
198 }
199 
200 #else
201 
202 #if (DE_OS == DE_OS_IOS)
203 #include "deThread.h" /*!< for deSleep() */
204 #endif
205 
206 #if defined(QP_USE_SIGNAL_HANDLER)
207 #include <signal.h>
208 #endif
209 
exitProcess(void)210 static void exitProcess(void)
211 {
212 #if (DE_OS == DE_OS_IOS)
213     /* Since tests are in the same process as execserver, we want to give it
214        a chance to stream complete log data before terminating. */
215     deSleep(5000);
216 #endif
217 
218 #if defined(QP_USE_SIGNAL_HANDLER)
219     /* QP_USE_SIGNAL_HANDLER defined, this means this function could have
220        been called from a signal handler. Calling exit() inside a signal
221        handler is not safe. */
222 
223     /* Flush all open FILES */
224     fflush(DE_NULL);
225 
226     /* Kill without calling any _at_exit handlers as those might hang */
227     raise(SIGKILL);
228 #else
229     exit(-1);
230 #endif
231 }
232 
233 #endif
234