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 
36 	MESSAGETYPE_LAST
37 } MessageType;
38 
39 static void		printRaw		(MessageType type, const char* msg);
40 static void		printFmt		(MessageType type, const char* fmt, va_list args);
41 static void		exitProcess		(void);
42 
qpPrint(const char * message)43 void qpPrint (const char* message)
44 {
45 	printRaw(MESSAGETYPE_INFO, message);
46 }
47 
qpPrintf(const char * format,...)48 void qpPrintf (const char* format, ...)
49 {
50 	va_list args;
51 	va_start(args, format);
52 	printFmt(MESSAGETYPE_INFO, format, args);
53 	va_end(args);
54 }
55 
qpPrintv(const char * format,va_list args)56 void qpPrintv (const char* format, va_list args)
57 {
58 	printFmt(MESSAGETYPE_INFO, format, args);
59 }
60 
qpDief(const char * format,...)61 void qpDief (const char* format, ...)
62 {
63 	va_list args;
64 	va_start(args, format);
65 	printFmt(MESSAGETYPE_ERROR, format, args);
66 	va_end(args);
67 
68 	exitProcess();
69 }
70 
qpDiev(const char * format,va_list args)71 void qpDiev (const char* format, va_list args)
72 {
73 	printFmt(MESSAGETYPE_ERROR, format, args);
74 	exitProcess();
75 }
76 
77 /* print() implementation. */
78 #if (DE_OS == DE_OS_ANDROID)
79 
80 #include <android/log.h>
81 
getLogPriority(MessageType type)82 static android_LogPriority getLogPriority (MessageType type)
83 {
84 	switch (type)
85 	{
86 		case MESSAGETYPE_INFO:	return ANDROID_LOG_INFO;
87 		case MESSAGETYPE_ERROR:	return ANDROID_LOG_FATAL;
88 		default:				return ANDROID_LOG_DEBUG;
89 	}
90 }
91 
printRaw(MessageType type,const char * message)92 void printRaw (MessageType type, const char* message)
93 {
94 	__android_log_write(getLogPriority(type), "dEQP", message);
95 }
96 
printFmt(MessageType type,const char * format,va_list args)97 void printFmt (MessageType type, const char* format, va_list args)
98 {
99 	__android_log_vprint(getLogPriority(type), "dEQP", format, args);
100 }
101 
102 #else
103 
getOutFile(MessageType type)104 static FILE* getOutFile (MessageType type)
105 {
106 	if (type == MESSAGETYPE_ERROR)
107 		return stderr;
108 	else
109 		return stdout;
110 }
111 
printRaw(MessageType type,const char * message)112 void printRaw (MessageType type, const char* message)
113 {
114 	FILE* out = getOutFile(type);
115 
116 	if (type == MESSAGETYPE_ERROR)
117 		fprintf(out, "FATAL ERROR: ");
118 
119 	fputs(message, out);
120 
121 	if (type == MESSAGETYPE_ERROR)
122 	{
123 		putc('\n', out);
124 		fflush(out);
125 	}
126 }
127 
printFmt(MessageType type,const char * format,va_list args)128 void printFmt (MessageType type, const char* format, va_list args)
129 {
130 	FILE* out = getOutFile(type);
131 
132 	if (type == MESSAGETYPE_ERROR)
133 		fprintf(out, "FATAL ERROR: ");
134 
135 	vfprintf(out, format, args);
136 
137 	if (type == MESSAGETYPE_ERROR)
138 	{
139 		putc('\n', out);
140 		fflush(out);
141 	}
142 }
143 
144 #endif
145 
146 /* exitProcess() implementation. */
147 #if (DE_OS == DE_OS_WIN32)
148 
149 #define NOMINMAX
150 #define VC_EXTRALEAN
151 #define WIN32_LEAN_AND_MEAN
152 #include <windows.h>
153 
exitProcess(void)154 static void exitProcess (void)
155 {
156 	/* Some API implementations register atexit() functions that may hang.
157 	   By using TerminateProcess() we can avoid calling any potentially hanging exit routines. */
158 	HANDLE curProc = GetCurrentProcess();
159 	TerminateProcess(curProc, -1);
160 }
161 
162 #else
163 
164 #if (DE_OS == DE_OS_IOS)
165 #	include "deThread.h"	/*!< for deSleep() */
166 #endif
167 
168 #if defined(QP_USE_SIGNAL_HANDLER)
169 #	include <signal.h>
170 #endif
171 
exitProcess(void)172 static void exitProcess (void)
173 {
174 #if (DE_OS == DE_OS_IOS)
175 	/* Since tests are in the same process as execserver, we want to give it
176 	   a chance to stream complete log data before terminating. */
177 	deSleep(5000);
178 #endif
179 
180 #if defined(QP_USE_SIGNAL_HANDLER)
181 	/* QP_USE_SIGNAL_HANDLER defined, this means this function could have
182 	   been called from a signal handler. Calling exit() inside a signal
183 	   handler is not safe. */
184 
185 	/* Flush all open FILES */
186 	fflush(DE_NULL);
187 
188 	/* Kill without calling any _at_exit handlers as those might hang */
189 	raise(SIGKILL);
190 #else
191 	exit(-1);
192 #endif
193 }
194 
195 #endif
196