X-Git-Url: https://feistymeow.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=nucleus%2Flibrary%2Floggers%2Fcritical_events.cpp;fp=nucleus%2Flibrary%2Floggers%2Fcritical_events.cpp;h=ebb60bb8245bca72e984426ee674318020db7d99;hb=457b128b77b5b4a0b7dd3094de543de2ce1477ad;hp=0000000000000000000000000000000000000000;hpb=32d7caf45d886d0d24e69eea00511c7815ac15d0;p=feisty_meow.git diff --git a/nucleus/library/loggers/critical_events.cpp b/nucleus/library/loggers/critical_events.cpp new file mode 100644 index 00000000..ebb60bb8 --- /dev/null +++ b/nucleus/library/loggers/critical_events.cpp @@ -0,0 +1,284 @@ +/*****************************************************************************\ +* * +* Name : critical_events * +* Author : Chris Koeritz * +* * +******************************************************************************* +* Copyright (c) 1989-$now By Author. This program is free software; you can * +* redistribute it and/or modify it under the terms of the GNU General Public * +* License as published by the Free Software Foundation; either version 2 of * +* the License or (at your option) any later version. This is online at: * +* http://www.fsf.org/copyleft/gpl.html * +* Please send any updates to: fred@gruntose.com * +\*****************************************************************************/ + +#include "critical_events.h" +#include "program_wide_logger.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef __UNIX__ + #include +#endif + +using namespace basis; +using namespace structures; +using namespace configuration; +using namespace textual; +using namespace timely; + +const int MESSAGE_SPACE_PROVIDED = 4096; + // the strings should not be larger than this for diagnostic / error messages. + +namespace loggers { + +SAFE_STATIC(astring, critical_events::hidden_critical_events_dir, ) + // define the function that holds the directory string. + +astring default_critical_location() +{ + // ensure that the critical events function logs to the appropriate place. + return application_configuration::get_logging_directory(); +} + +SAFE_STATIC(mutex, __critical_event_dir_lock, ) + +basis::un_int critical_events::system_error() +{ +#if defined(__UNIX__) + return errno; +#elif defined(__WIN32__) + return GetLastError(); +#else + #pragma error("hmmm: no code for error number for this operating system") + return 0; +#endif +} + +astring critical_events::system_error_text(basis::un_int to_name) +{ +#if defined(__UNIX__) + return strerror(to_name); +#elif defined(__WIN32__) + char error_text[1000]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NIL, to_name, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)error_text, + sizeof(error_text) - 1, NIL); + astring to_return = error_text; + // trim off the ridiculous carriage return they add. + while ( (to_return[to_return.end()] == '\r') + || (to_return[to_return.end()] == '\n') ) + to_return.zap(to_return.end(), to_return.end()); + return to_return; +#else + #pragma error("hmmm: no code for error text for this operating system") + return ""; +#endif +} + +astring critical_events::critical_events_directory() +{ + static bool initted = false; + if (!initted) { + auto_synchronizer l(__critical_event_dir_lock()); + if (!initted) { + set_critical_events_directory(default_critical_location()); + initted = true; + } + } + return hidden_critical_events_dir(); +} + +void critical_events::set_critical_events_directory(const astring &directory) +{ hidden_critical_events_dir() = directory; } + +void critical_events::write_to_critical_events(const char *to_write) +{ + astring filename = critical_events_directory(); + filename += "/runtime_issues.log"; + FILE *errfile = fopen(filename.s(), "ab"); + if (errfile) { + astring app_name = application_configuration::application_name(); + int indy = app_name.find('/', app_name.end(), true); + if (non_negative(indy)) app_name.zap(0, indy); + indy = app_name.find('\\', app_name.end(), true); + if (non_negative(indy)) app_name.zap(0, indy); + fprintf(errfile, "%s [%s]:%s", time_stamp::notarize(true).s(), + app_name.s(), parser_bits::platform_eol_to_chars()); + fprintf(errfile, "%s%s", to_write, parser_bits::platform_eol_to_chars()); + fclose(errfile); + } +} + +void critical_events::write_to_console(const char *guards_message_space) +{ fprintf(stderr, "%s", (char *)guards_message_space); fflush(stderr); } + +void critical_events::alert_message(const char *info, const char *title) +{ + astring to_print; + if (strlen(title)) { + const char border = '='; + to_print += astring(border, int(strlen(title)) + 4); + to_print += parser_bits::platform_eol_to_chars(); + to_print += border; + to_print += ' '; + to_print += title; + to_print += ' '; + to_print += border; + to_print += parser_bits::platform_eol_to_chars(); + to_print += astring(border, int(strlen(title)) + 4); + to_print += parser_bits::platform_eol_to_chars(); + } + + to_print += info; + program_wide_logger::get().log(to_print, ALWAYS_PRINT); + fflush(NIL); // flush all output streams. +} + +void critical_events::alert_message(const astring &info) { alert_message(info.s()); } + +void critical_events::alert_message(const astring &info, const astring &title) +{ alert_message(info.s(), title.s()); } + +void critical_events::make_error_message(const char *file, int line, + const char *error_class, const char *error_function, + const char *info, char *guards_message_space) +{ + strcpy(guards_message_space, "\nProblem reported for \""); +//hmmm: only copy N chars of each into the space. +// say 40 for class/function each, then the space - consumed for the +// info. get strlen for real on the class and function name to know +// actual size for that computation. + strcat(guards_message_space, error_class); + strcat(guards_message_space, "::"); + strcat(guards_message_space, error_function); + strcat(guards_message_space, "\"\n(invoked at line "); + char line_num[20]; + sprintf(line_num, "%d", line); + strcat(guards_message_space, line_num); + strcat(guards_message_space, " in "); + strcat(guards_message_space, file); + strcat(guards_message_space, " at "); + strcat(guards_message_space, time_stamp::notarize(false).s()); + strcat(guards_message_space, ")\n"); + strcat(guards_message_space, info); + strcat(guards_message_space, "\n\n\n"); +} + +void critical_events::FL_deadly_error(const char *file, int line, const char *error_class, + const char *error_function, const char *info) +{ + FL_continuable_error(file, line, error_class, error_function, info, + "Deadly Error Information"); + CAUSE_BREAKPOINT; + throw "deadly_error"; + // abort() is not as good an approach as throwing an exception. aborts are + // harder to track with some compilers, but all should be able to trap an + // exception. +} + +void critical_events::FL_deadly_error(const astring &file, int line, + const astring &error_class, const astring &error_function, + const astring &info) +{ + FL_deadly_error(file.s(), line, error_class.s(), error_function.s(), + info.s()); +} + +void critical_events::FL_continuable_error_real(const char *file, int line, + const char *error_class, const char *error_function, const char *info, + const char *title) +{ + char guards_message_space[MESSAGE_SPACE_PROVIDED]; + // this routine could still fail, if the call stack is already jammed + // against its barrier. but if that's the case, even the simple function + // call might fail. in any case, we cannot deal with a stack overflow + // type error using this function. but we would rather deal with that + // than make the space static since that would cause corruption when + // two threads wrote errors at the same time. + make_error_message(file, line, error_class, error_function, info, + guards_message_space); + alert_message(guards_message_space, title); +} + +void critical_events::FL_continuable_error(const char *file, int line, + const char *error_class, const char *error_function, const char *info, + const char *title) +{ + FL_continuable_error_real(file, line, error_class, error_function, info, title); +} + +void critical_events::FL_continuable_error(const astring &file, int line, + const astring &error_class, const astring &error_function, + const astring &info, const astring &title) +{ + FL_continuable_error_real(file.s(), line, error_class.s(), + error_function.s(), info.s(), title.s()); +} + +void critical_events::FL_non_continuable_error(const char *file, int line, + const char *error_class, const char *error_function, const char *info, + const char *title) +{ + FL_continuable_error_real(file, line, error_class, error_function, info, + title); + exit(EXIT_FAILURE); // let the outside world know that there was a problem. +} + +void critical_events::FL_non_continuable_error(const astring &file, int line, + const astring &error_class, const astring &error_function, + const astring &info, const astring &title) +{ + FL_continuable_error_real(file.s(), line, error_class.s(), + error_function.s(), info.s(), title.s()); + exit(EXIT_FAILURE); // let the outside world know that there was a problem. +} + +void critical_events::FL_console_error(const char *file, int line, const char *error_class, + const char *error_function, const char *info) +{ + char guards_message_space[MESSAGE_SPACE_PROVIDED]; + make_error_message(file, line, error_class, error_function, info, + guards_message_space); + write_to_console(guards_message_space); +} + +void critical_events::FL_out_of_memory_now(const char *file, int line, + const char *the_class_name, const char *the_func) +{ + FL_non_continuable_error(file, line, the_class_name, the_func, + "Program stopped due to memory allocation failure.", + "Out of Memory Now"); +} + +void critical_events::implement_bounds_halt(const char *the_class_name, const char *the_func, + const char *value, const char *low, const char *high, + const char *error_addition) +{ + char message[400]; + strcpy(message, "bounds error caught"); + strcat(message, error_addition); + strcat(message, ":\r\n"); + strcat(message, value); + strcat(message, " is not between "); + strcat(message, low); + strcat(message, " and "); + strcat(message, high); +#ifdef ERRORS_ARE_FATAL + deadly_error(the_class_name, the_func, message); +#else + continuable_error(the_class_name, the_func, message); +#endif +} + +} //namespace. +