00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "CSConfig.h"
00029
00030 #ifdef OS_WINDOWS
00031 #define strsignal(s) NULL
00032 #else
00033 #include <sys/signal.h>
00034 #endif
00035
00036 #include <limits.h>
00037 #include <string.h>
00038
00039 #include "CSGlobal.h"
00040 #include "CSException.h"
00041 #include "CSStrUtil.h"
00042 #include "CSLog.h"
00043
00044 void CSException::setStackTrace(CSThread *self, const char *stack)
00045 {
00046 char buffer[CS_EXC_CONTEXT_SIZE];
00047
00048 self->myException.iStackTrace.setLength(0);
00049 if (stack)
00050 self->myException.iStackTrace.append(stack);
00051 for (int i=self->callTop-1; i>=0; i--) {
00052 cs_format_context(CS_EXC_CONTEXT_SIZE, buffer,
00053 self->callStack[i].cs_func, self->callStack[i].cs_file, self->callStack[i].cs_line);
00054 self->myException.iStackTrace.append(buffer);
00055 self->myException.iStackTrace.append('\n');
00056 }
00057 }
00058
00059 void CSException::setStackTrace(CSThread *self)
00060 {
00061 setStackTrace(self, NULL);
00062 }
00063
00064 const char *CSException::getStackTrace()
00065 {
00066 return iStackTrace.getCString();
00067 }
00068
00069 void CSException::log(CSThread *self)
00070 {
00071 CSL.lock();
00072 CSL.log(self, CSLog::Error, getContext());
00073 CSL.log(self, CSLog::Error, " ");
00074 CSL.log(self, CSLog::Error, getMessage());
00075 CSL.eol(self, CSLog::Error);
00076 #ifdef DUMP_STACK_TRACE
00077 CSL.log(self, CSLog::Error, getStackTrace());
00078 #endif
00079 CSL.unlock();
00080 }
00081
00082 void CSException::log(CSThread *self, const char *message)
00083 {
00084 CSL.lock();
00085 CSL.log(self, CSLog::Error, message);
00086 CSL.eol(self, CSLog::Error);
00087 CSL.log(self, CSLog::Error, getContext());
00088 CSL.log(self, CSLog::Error, " ");
00089 CSL.log(self, CSLog::Error, getMessage());
00090 CSL.eol(self, CSLog::Error);
00091 #ifdef DUMP_STACK_TRACE
00092 CSL.log(self, CSLog::Error, getStackTrace());
00093 #endif
00094 CSL.unlock();
00095 }
00096
00097 void CSException::initException_va(const char *func, const char *file, int line, int err, const char *fmt, va_list ap)
00098 {
00099
00100 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00101 iErrorCode = err;
00102 #ifdef OS_WINDOWS
00103 vsprintf(iMessage, fmt, ap);
00104 #else
00105 size_t len;
00106 len = vsnprintf(iMessage, CS_EXC_MESSAGE_SIZE-1, fmt, ap);
00107 if (len > CS_EXC_MESSAGE_SIZE-1)
00108 len = CS_EXC_MESSAGE_SIZE-1;
00109 iMessage[len] = 0;
00110 #endif
00111 }
00112
00113 void CSException::initExceptionf(const char *func, const char *file, int line, int err, const char *fmt, ...)
00114 {
00115 va_list ap;
00116
00117 va_start(ap, fmt);
00118 initException_va(func, file, line, err, fmt, ap);
00119 va_end(ap);
00120 }
00121
00122 void CSException::initException(const char *func, const char *file, int line, int err, const char *message)
00123 {
00124 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00125 iErrorCode = err;
00126 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, message);
00127 }
00128
00129 void CSException::initException(CSException &exception)
00130 {
00131 iErrorCode = exception.iErrorCode;
00132 strcpy(iContext, exception.iContext);
00133 strcpy(iMessage, exception.iMessage);
00134
00135 iStackTrace.setLength(0);
00136 iStackTrace.append(exception.iStackTrace.getCString());
00137
00138 }
00139
00140 void CSException::initAssertion(const char *func, const char *file, int line, const char *message)
00141 {
00142 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00143 iErrorCode = CS_ERR_ASSERTION;
00144 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "Assertion failed: ");
00145 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, message);
00146 }
00147
00148 void CSException::getCoreError(uint32_t size, char *buffer, int err)
00149 {
00150 const char *message = NULL;
00151
00152 switch (err) {
00153 case CS_ERR_JUMP_OVERFLOW: message = "Jump stack overflow"; break;
00154 case CS_ERR_BAD_ADDRESS: message = "Incorrect network address: %"; break;
00155 case CS_ERR_UNKNOWN_SERVICE: message = "Unknown network service: %"; break;
00156 case CS_ERR_UNKNOWN_HOST: message = "Unknown host: %"; break;
00157 case CS_ERR_UNKNOWN_METHOD: message = "Unknown HTTP method: %"; break;
00158 case CS_ERR_NO_LISTENER: message = "Listening port has been closed"; break;
00159 case CS_ERR_RELEASE_OVERFLOW: message = "Release stack overflow"; break;
00160 case CS_ERR_IMPL_MISSING: message = "Function %s not implemented"; break;
00161 case CS_ERR_BAD_HEADER_MAGIC: message = "Incorrect file type"; break;
00162 case CS_ERR_VERSION_TOO_NEW: message = "Incompatible file version"; break;
00163 }
00164 if (message)
00165 cs_strcpy(size, buffer, message);
00166 else {
00167 cs_strcpy(size, buffer, "Unknown system error ");
00168 cs_strcat(size, buffer, err);
00169 }
00170 }
00171
00172 void CSException::initCoreError(const char *func, const char *file, int line, int err)
00173 {
00174 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00175 iErrorCode = err;
00176 getCoreError(CS_EXC_MESSAGE_SIZE, iMessage, err);
00177 }
00178
00179 void CSException::initCoreError(const char *func, const char *file, int line, int err, const char *item)
00180 {
00181 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00182 iErrorCode = err;
00183 getCoreError(CS_EXC_MESSAGE_SIZE, iMessage, err);
00184 cs_replace_string(CS_EXC_MESSAGE_SIZE, iMessage, "%s", item);
00185 }
00186
00187 void CSException::initOSError(const char *func, const char *file, int line, int err)
00188 {
00189 char *msg;
00190
00191 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00192 iErrorCode = err;
00193
00194 #ifdef XT_WIN
00195 if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, iMessage, CS_EXC_MESSAGE_SIZE, NULL)) {
00196 char *ptr;
00197
00198 ptr = &iMessage[strlen(iMessage)];
00199 while (ptr-1 > err_msg) {
00200 if (*(ptr-1) != '\n' && *(ptr-1) != '\r' && *(ptr-1) != '.')
00201 break;
00202 ptr--;
00203 }
00204 *ptr = 0;
00205
00206 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
00207 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
00208 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
00209 return;
00210 }
00211 #endif
00212
00213 msg = strerror(err);
00214 if (msg) {
00215 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, msg);
00216 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
00217 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
00218 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
00219 }
00220 else {
00221 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "Unknown OS error code ");
00222 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, err);
00223 }
00224 }
00225
00226 void CSException::initFileError(const char *func, const char *file, int line, const char *path, int err)
00227 {
00228 initOSError(func, file, line, err);
00229 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ": '");
00230 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, path);
00231 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, "'");
00232 }
00233
00234 void CSException::initSignal(const char *func, const char *file, int line, int sig)
00235 {
00236 char *str;
00237
00238 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00239 iErrorCode = sig;
00240 if (!(str = strsignal(sig))) {
00241 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "Unknown signal ");
00242 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, sig);
00243 }
00244 else {
00245 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, str);
00246 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, " (");
00247 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, sig);
00248 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, ")");
00249 }
00250 }
00251
00252 void CSException::initEOFError(const char *func, const char *file, int line, const char *path)
00253 {
00254 cs_format_context(CS_EXC_CONTEXT_SIZE, iContext, func, file, line);
00255 iErrorCode = CS_ERR_EOF;
00256 cs_strcpy(CS_EXC_MESSAGE_SIZE, iMessage, "EOF encountered: '");
00257 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, path);
00258 cs_strcat(CS_EXC_MESSAGE_SIZE, iMessage, "'");
00259 }
00260
00261 void CSException::RecordException(const char *func, const char *file, int line, int err, const char *message)
00262 {
00263 CSThread *self;
00264
00265 if ((self = CSThread::getSelf())) {
00266 if (!self->myException.getErrorCode())
00267 self->myException.initException(func, file, line, err, message);
00268 }
00269 }
00270
00271 void CSException::ClearException()
00272 {
00273 CSThread *self;
00274
00275 if ((self = CSThread::getSelf())) {
00276 self->myException.setErrorCode(0);
00277 }
00278 }
00279
00280 void CSException::throwException(const char *func, const char *file, int line, int err, const char *message, const char *stack)
00281 {
00282 CSThread *self;
00283
00284 if ((self = CSThread::getSelf())) {
00285 self->myException.initException(func, file, line, err, message);
00286 self->myException.setStackTrace(self, stack);
00287 self->throwException();
00288 }
00289 else {
00290 CSException e;
00291
00292 e.initException(func, file, line, err, message);
00293 e.log(NULL, "*** Uncaught error");
00294 }
00295 }
00296
00297 void CSException::throwException(const char *func, const char *file, int line, int err, const char *message)
00298 {
00299 throwException(func, file, line, err, message, NULL);
00300 }
00301
00302 void CSException::throwExceptionf(const char *func, const char *file, int line, int err, const char *fmt, ...)
00303 {
00304 CSThread *self;
00305 va_list ap;
00306
00307 va_start(ap, fmt);
00308 if ((self = CSThread::getSelf())) {
00309 self->myException.initException_va(func, file, line, err, fmt, ap);
00310 va_end(ap);
00311 self->myException.setStackTrace(self, NULL);
00312 self->throwException();
00313 }
00314 else {
00315 CSException e;
00316
00317 e.initException_va(func, file, line, err, fmt, ap);
00318 va_end(ap);
00319 e.log(NULL, "*** Uncaught error");
00320 }
00321 }
00322
00323 void CSException::throwAssertion(const char *func, const char *file, int line, const char *message)
00324 {
00325 CSThread *self;
00326
00327 if ((self = CSThread::getSelf())) {
00328 self->myException.initAssertion(func, file, line, message);
00329 self->myException.setStackTrace(self);
00330
00331
00332
00333 self->throwException();
00334 }
00335 else {
00336 CSException e;
00337
00338 e.initAssertion(func, file, line, message);
00339 e.log(NULL, "*** Uncaught error");
00340 }
00341 }
00342
00343 void CSException::throwCoreError(const char *func, const char *file, int line, int err)
00344 {
00345 CSThread *self;
00346
00347 if ((self = CSThread::getSelf())) {
00348 self->myException.initCoreError(func, file, line, err);
00349 self->myException.setStackTrace(self);
00350 self->throwException();
00351 }
00352 else {
00353 CSException e;
00354
00355 e.initCoreError(func, file, line, err);
00356 e.log(NULL, "*** Uncaught error");
00357 }
00358 }
00359
00360 void CSException::throwCoreError(const char *func, const char *file, int line, int err, const char *item)
00361 {
00362 CSThread *self;
00363
00364 if ((self = CSThread::getSelf())) {
00365 self->myException.initCoreError(func, file, line, err, item);
00366 self->myException.setStackTrace(self);
00367 self->throwException();
00368 }
00369 else {
00370 CSException e;
00371
00372 e.initCoreError(func, file, line, err, item);
00373 e.log(NULL, "*** Uncaught error");
00374 }
00375 }
00376
00377 void CSException::throwOSError(const char *func, const char *file, int line, int err)
00378 {
00379 CSThread *self;
00380
00381 if ((self = CSThread::getSelf())) {
00382
00383
00384
00385
00386 self->interrupted();
00387 self->myException.initOSError(func, file, line, err);
00388 self->myException.setStackTrace(self);
00389 self->throwException();
00390 }
00391 else {
00392 CSException e;
00393
00394 e.initOSError(func, file, line, err);
00395 e.log(NULL, "*** Uncaught error");
00396 }
00397 }
00398
00399 void CSException::throwFileError(const char *func, const char *file, int line, const char *path, int err)
00400 {
00401 CSThread *self;
00402
00403 if ((self = CSThread::getSelf())) {
00404 self->interrupted();
00405 self->myException.initFileError(func, file, line, path, err);
00406 self->myException.setStackTrace(self);
00407 self->throwException();
00408 }
00409 else {
00410 CSException e;
00411
00412 e.initFileError(func, file, line, path, err);
00413 e.log(NULL, "*** Uncaught error");
00414 }
00415 }
00416
00417 void CSException::throwFileError(const char *func, const char *file, int line, CSString *path, int err)
00418 {
00419 CSThread *self;
00420
00421 if ((self = CSThread::getSelf())) {
00422 self->interrupted();
00423 self->myException.initFileError(func, file, line, path->getCString(), err);
00424 self->myException.setStackTrace(self);
00425 self->throwException();
00426 }
00427 else {
00428 CSException e;
00429
00430 e.initFileError(func, file, line, path->getCString(), err);
00431 e.log(NULL, "*** Uncaught error");
00432 }
00433 }
00434
00435 void CSException::throwSignal(const char *func, const char *file, int line, int sig)
00436 {
00437 CSThread *self;
00438
00439 if ((self = CSThread::getSelf())) {
00440 self->myException.initSignal(func, file, line, sig);
00441 self->myException.setStackTrace(self);
00442 self->throwException();
00443 }
00444 else {
00445 CSException e;
00446
00447 e.initSignal(func, file, line, sig);
00448 e.log(NULL, "*** Uncaught error");
00449 }
00450 }
00451
00452 void CSException::throwEOFError(const char *func, const char *file, int line, const char *path)
00453 {
00454 CSThread *self;
00455
00456 if ((self = CSThread::getSelf())) {
00457 self->interrupted();
00458 self->myException.initEOFError(func, file, line, path);
00459 self->myException.setStackTrace(self);
00460 self->throwException();
00461 }
00462 else {
00463 CSException e;
00464
00465 e.initEOFError(func, file, line, path);
00466 e.log(NULL, "*** Uncaught error");
00467 }
00468 }
00469
00470 void CSException::throwLastError(const char *func, const char *file, int line)
00471 {
00472 #ifdef OS_WINDOWS
00473 throwOSError(func, file, line, (int) GetLastError());
00474 #else
00475 throwOSError(func, file, line, (int) errno);
00476 #endif
00477 }
00478
00479 void CSException::logOSError(const char *func, const char *file, int line, int err)
00480 {
00481 CSThread *self;
00482
00483 if ((self = CSThread::getSelf())) {
00484 self->myException.initOSError(func, file, line, err);
00485 self->myException.setStackTrace(self);
00486 self->logException();
00487 }
00488 else {
00489 CSException e;
00490
00491 e.initOSError(func, file, line, err);
00492 e.log(NULL);
00493 }
00494 }
00495
00496 void CSException::logOSError(CSThread *self, const char *func, const char *file, int line, int err)
00497 {
00498 self->myException.initOSError(func, file, line, err);
00499 self->myException.setStackTrace(self);
00500 self->logException();
00501 }
00502
00503 void CSException::logException(const char *func, const char *file, int line, int err, const char *message)
00504 {
00505 CSThread *self;
00506
00507 if ((self = CSThread::getSelf())) {
00508 self->myException.initException(func, file, line, err, message);
00509 self->logException();
00510 }
00511 else {
00512 CSException e;
00513
00514 e.initException(func, file, line, err,message);
00515 e.log(NULL);
00516 }
00517 }
00518
00519