diff --git a/api/boinc_api.C b/api/boinc_api.C index be290af6d7..70149dc258 100644 --- a/api/boinc_api.C +++ b/api/boinc_api.C @@ -20,20 +20,12 @@ // Code that's in the BOINC app library (but NOT in the core client) // graphics-related code goes in graphics_api.C, not here -#include -#include -#include - #ifdef _WIN32 -#include -#include #include -#include -#include // for timing #include "win/Stackwalker.h" #endif -#if HAVE_UNISTD_H +#ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_TIME_H @@ -41,6 +33,10 @@ #include #endif +#include +#include +#include +#include #include #include #include @@ -51,38 +47,487 @@ #include "filesys.h" #include "error_numbers.h" #include "app_ipc.h" - #include "boinc_api.h" + +// +// Declare global variables +// +static APP_INIT_DATA aid; + APP_CLIENT_SHM *app_client_shm; + +static double timer_period = 1.0/50.0; // 50 Hz timer +static double time_until_checkpoint; +static double time_until_fraction_done_update; +static double fraction_done; +static double last_checkpoint_cpu_time; +static bool ready_to_checkpoint = false; +static bool this_process_active; +static bool time_to_quit = false; +static double last_wu_cpu_time; +static bool standalone = false; +static double initial_wu_cpu_time; +static bool have_new_trickle = false; + + + #ifdef _WIN32 -HANDLE hQuitRequest, hSharedMem, worker_thread_handle; -LONG CALLBACK boinc_catch_signal(EXCEPTION_POINTERS *ExceptionInfo); -MMRESULT timer_id; -#else -extern void boinc_catch_signal(int signal); -extern void boinc_quit(int sig); + +// Declare global variables - Windows Platform Only + HANDLE hErrorNotification; + HANDLE hQuitRequest; + HANDLE hSuspendRequest; + HANDLE hResumeRequest; + HANDLE hSharedMem; + HANDLE worker_thread_handle; + MMRESULT timer_id; + #endif -static APP_INIT_DATA aid; -static double timer_period = 1.0/50.0; // 50 Hz timer -static double time_until_checkpoint; -static double time_until_fraction_done_update; -static double fraction_done; -static double last_checkpoint_cpu_time; -static bool ready_to_checkpoint = false; -static bool this_process_active; -static bool time_to_quit = false; -static double last_wu_cpu_time; -static bool standalone = false; -static double initial_wu_cpu_time; -static bool have_new_trickle = false; -APP_CLIENT_SHM *app_client_shm; +// +// Forward declare implementation functions. +// +static void setup_shared_mem(); +static void cleanup_shared_mem(); +static int update_app_progress(double frac_done, double cpu_t, double cp_cpu_t, double ws_t); +static int set_timer(double period); + +#ifdef _WIN32 + +// Forward declare implementation functions - Windows Platform Only. +LONG CALLBACK boinc_catch_signal(EXCEPTION_POINTERS *ExceptionInfo); + +#else + +// Forward declare implementation functions - POSIX Platform Only. +extern void boinc_catch_signal(int signal); +extern void boinc_quit(int sig); + +#endif + + +// **************************************************************************** +// **************************************************************************** +// +// Diagnostics Support for Windows 95/98/ME/2000/XP/2003 +// +// **************************************************************************** +// **************************************************************************** + +#ifdef _WIN32 + +// +// Function: boinc_install_signal_handlers +// +// Purpose: Used to setup an unhandled exception filter on Windows +// +// Date: 01/29/04 +// +int boinc_install_signal_handlers() { + + SetUnhandledExceptionFilter( boinc_catch_signal ); + + return 0; +} + +// +// Function: boinc_catch_signal +// +// Purpose: Used to unwind the stack and spew the callstack to stderr. Terminate the +// process afterwards and return the exception code as the exit code. +// +// Date: 01/29/04 +// +LONG CALLBACK boinc_catch_signal(EXCEPTION_POINTERS *pExPtrs) { + + // Snagged from the latest stackwalker code base. This allows us to grab + // callstacks even in a stack overflow scenario + if ( pExPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW ) + { + static char MyStack[1024*128]; // be sure that we have enought space... + // it assumes that DS and SS are the same!!! (this is the case for Win32) + // change the stack only if the selectors are the same (this is the case for Win32) + //__asm push offset MyStack[1024*128]; + //__asm pop esp; + __asm mov eax,offset MyStack[1024*128]; + __asm mov esp,eax; + } + + PVOID exceptionAddr = pExPtrs->ExceptionRecord->ExceptionAddress; + DWORD exceptionCode = pExPtrs->ExceptionRecord->ExceptionCode; + + LONG lReturnValue = NULL; + char status[256]; + char substatus[256]; + + static long lDetectNestedException = 0; + + // If we've been in this procedure before, something went wrong so we immediately exit + if ( InterlockedIncrement(&lDetectNestedException) > 1 ) { + TerminateProcess( GetCurrentProcess(), ERR_SIGNAL_CATCH ); + } + + switch ( exceptionCode ) { + case EXCEPTION_ACCESS_VIOLATION: + safe_strncpy( status, "Access Violation", sizeof(status) ); + if ( pExPtrs->ExceptionRecord->NumberParameters == 2 ) { + switch( pExPtrs->ExceptionRecord->ExceptionInformation[0] ) { + case 0: // read attempt + sprintf( substatus, "read attempt to address 0x%8.8X", pExPtrs->ExceptionRecord->ExceptionInformation[1] ); + break; + case 1: // write attempt + sprintf( substatus, "write attempt to address 0x%8.8X", pExPtrs->ExceptionRecord->ExceptionInformation[1] ); + break; + } + } + break; + case EXCEPTION_DATATYPE_MISALIGNMENT: + safe_strncpy( status, "Data Type Misalignment", sizeof(status) ); + break; + case EXCEPTION_BREAKPOINT: + safe_strncpy( status, "Breakpoint Encountered", sizeof(status) ); + break; + case EXCEPTION_SINGLE_STEP: + safe_strncpy( status, "Single Instruction Executed", sizeof(status) ); + break; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + safe_strncpy( status, "Array Bounds Exceeded", sizeof(status) ); + break; + case EXCEPTION_FLT_DENORMAL_OPERAND: + safe_strncpy( status, "Float Denormal Operand", sizeof(status) ); + break; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + safe_strncpy( status, "Divide by Zero", sizeof(status) ); + break; + case EXCEPTION_FLT_INEXACT_RESULT: + safe_strncpy( status, "Float Inexact Result", sizeof(status) ); + break; + case EXCEPTION_FLT_INVALID_OPERATION: + safe_strncpy( status, "Float Invalid Operation", sizeof(status) ); + break; + case EXCEPTION_FLT_OVERFLOW: + safe_strncpy( status, "Float Overflow", sizeof(status) ); + break; + case EXCEPTION_FLT_STACK_CHECK: + safe_strncpy( status, "Float Stack Check", sizeof(status) ); + break; + case EXCEPTION_FLT_UNDERFLOW: + safe_strncpy( status, "Float Underflow", sizeof(status) ); + break; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + safe_strncpy( status, "Integer Divide by Zero", sizeof(status) ); + break; + case EXCEPTION_INT_OVERFLOW: + safe_strncpy( status, "Integer Overflow", sizeof(status) ); + break; + case EXCEPTION_PRIV_INSTRUCTION: + safe_strncpy( status, "Privileged Instruction", sizeof(status) ); + break; + case EXCEPTION_IN_PAGE_ERROR: + safe_strncpy( status, "In Page Error", sizeof(status) ); + break; + case EXCEPTION_ILLEGAL_INSTRUCTION: + safe_strncpy( status, "Illegal Instruction", sizeof(status) ); + break; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + safe_strncpy( status, "Noncontinuable Exception", sizeof(status) ); + break; + case EXCEPTION_STACK_OVERFLOW: + safe_strncpy( status, "Stack Overflow", sizeof(status) ); + break; + case EXCEPTION_INVALID_DISPOSITION: + safe_strncpy( status, "Invalid Disposition", sizeof(status) ); + break; + case EXCEPTION_GUARD_PAGE: + safe_strncpy( status, "Guard Page Violation", sizeof(status) ); + break; + case EXCEPTION_INVALID_HANDLE: + safe_strncpy( status, "Invalid Handle", sizeof(status) ); + break; + case CONTROL_C_EXIT: + safe_strncpy( status, "Ctrl+C Exit", sizeof(status) ); + break; + default: + safe_strncpy( status, "Unknown exception", sizeof(status) ); + break; + } + + fprintf( stderr, "\n***UNHANDLED EXCEPTION****\n" ); + if ( EXCEPTION_ACCESS_VIOLATION == exceptionCode ) { + fprintf( stderr, "Reason: %s (0x%x) at address 0x%p %s\n\n", status, exceptionCode, exceptionAddr, substatus ); + } else { + fprintf( stderr, "Reason: %s (0x%x) at address 0x%p\n\n", status, exceptionCode, exceptionAddr ); + } + fflush(stderr); + +#ifdef _DEBUG + // Unwind the stack and spew it to stderr + StackwalkFilter(pExPtrs, EXCEPTION_EXECUTE_HANDLER, NULL); +#endif + + fprintf(stderr, "Exiting...\n"); + fflush(stderr); + + // Force terminate the app letting BOINC know an unknown exception has occurred. + TerminateProcess(GetCurrentProcess(), pExPtrs->ExceptionRecord->ExceptionCode); + + // We won't make it to this point, but make the compiler happy anyway. + return 1; +} + + +// +// Function: boinc_message_reporting +// +// Purpose: Trap ASSERTs and TRACEs from the CRT and spew them to stderr. +// +// Date: 01/29/04 +// +int __cdecl boinc_message_reporting( int reportType, char *szMsg, int *retVal ){ + (*retVal) = 0; + + switch(reportType){ + + case _CRT_WARN: + fprintf( stderr, "TRACE: %s", szMsg ); + fflush( stderr ); + break; + case _CRT_ERROR: + fprintf( stderr, "ERROR: %s", szMsg ); + fflush( stderr ); + break; + case _CRT_ASSERT: + fprintf( stderr, "ASSERT: %s\n", szMsg ); + fflush( stderr ); + (*retVal) = 1; + break; + + } + + return(TRUE); +} + + +#ifdef _DEBUG + +// +// Function: boinc_trace +// +// Purpose: Converts the BOINCTRACE macro into a single string and report it +// to the CRT so it can be reported via the normal means. +// +// Date: 01/29/04 +// +void boinc_trace(const char *pszFormat, ...) +{ + static char szBuffer[4096]; + + memset(szBuffer, 0, sizeof(szBuffer)); + + va_list ptr; + va_start(ptr, pszFormat); + + BOINCASSERT( -1 != _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, ptr) ); + + va_end(ptr); + + _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%s", szBuffer); +} + + +// +// Function: boinc_error_debug +// +// Purpose: Converts the BOINCERROR macro into a single string and report it +// to the CRT so it can be reported via the normal means. +// +// Date: 01/29/04 +// +void boinc_error_debug(int iExitCode, const char *pszFormat, ...) +{ + static char szBuffer[4096]; + + memset(szBuffer, 0, sizeof(szBuffer)); + + va_list ptr; + va_start(ptr, pszFormat); + + BOINCASSERT( -1 != _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, ptr) ); + + va_end(ptr); + + _CrtDbgReport(_CRT_ERROR, NULL, NULL, NULL, "%s", szBuffer); +} + +#else // _DEBUG + +// +// Function: boinc_error_release +// +// Purpose: Converts the BOINCERROR macro into a single string and report it +// to stderr so it can be reported via the normal means. +// +// Date: 01/29/04 +// +void boinc_error_release(int iExitCode, const char *pszFormat, ...) +{ + static char szBuffer[4096]; + + memset(szBuffer, 0, sizeof(szBuffer)); + + va_list ptr; + va_start(ptr, pszFormat); + + _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, ptr); + + va_end(ptr); + + fprintf( stderr, "ERROR: %s", szBuffer ); + fflush( stderr ); +} + + +#endif // _DEBUG + +#endif // _WIN32 + + +// **************************************************************************** +// **************************************************************************** +// +// Diagnostics for POSIX Compatible systems. +// +// **************************************************************************** +// **************************************************************************** + +#ifdef HAVE_SIGNAL_H + +int boinc_install_signal_handlers() { + signal(SIGHUP, boinc_catch_signal); // terminal line hangup + signal(SIGINT, boinc_catch_signal); // interrupt program + signal(SIGQUIT, boinc_quit); // quit program + signal(SIGILL, boinc_catch_signal); // illegal instruction + signal(SIGABRT, boinc_catch_signal); // abort(2) call + signal(SIGBUS, boinc_catch_signal); // bus error + signal(SIGSEGV, boinc_catch_signal); // segmentation violation + signal(SIGSYS, boinc_catch_signal); // system call given invalid argument + signal(SIGPIPE, boinc_catch_signal); // write on a pipe with no reader + return 0; +} + +void boinc_catch_signal(int signal) { + switch(signal) { + case SIGHUP: fprintf(stderr, "SIGHUP: terminal line hangup"); break; + case SIGINT: fprintf(stderr, "SIGINT: interrupt program"); break; + case SIGILL: fprintf(stderr, "SIGILL: illegal instruction"); break; + case SIGABRT: fprintf(stderr, "SIGABRT: abort called"); break; + case SIGBUS: fprintf(stderr, "SIGBUS: bus error"); break; + case SIGSEGV: fprintf(stderr, "SIGSEGV: segmentation violation"); break; + case SIGSYS: fprintf(stderr, "SIGSYS: system call given invalid argument"); break; + case SIGPIPE: fprintf(stderr, "SIGPIPE: write on a pipe with no reader"); break; + default: fprintf(stderr, "unknown signal %d", signal); break; + } + fprintf(stderr, "\nExiting...\n"); + exit(ERR_SIGNAL_CATCH); +} + +void boinc_quit(int sig) { + signal(SIGQUIT, boinc_quit); // reset signal + time_to_quit = true; +} + +#endif + + +// **************************************************************************** +// **************************************************************************** +// +// Standard BOINC API's +// +// **************************************************************************** +// **************************************************************************** + + +int boinc_init(bool standalone_ /* = false */) { + FILE* f; + int retval; + +#ifdef _WIN32 + + // Redirect stderr earlier then boinc_init so we can trap errors earlier. + freopen(STDERR_FILE, "a", stderr); + + // Define how messages should me formatted to sdterr + _CrtSetReportHook( boinc_message_reporting ); + + DuplicateHandle( + GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &worker_thread_handle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS + ); + +#endif + + // Install unhandled exception filters and signal traps. + boinc_install_signal_handlers(); + + // Store startup mode for later use. + standalone = standalone_; + + // Parse initial data file. + retval = boinc_parse_init_data_file(); + if (retval) return retval; + + // copy the WU CPU time to a separate var, + // since we may reread the structure again later. + // + initial_wu_cpu_time = aid.wu_cpu_time; + + f = boinc_fopen(FD_INIT_FILE, "r"); + if (f) { + parse_fd_init_file(f); + fclose(f); + } + + time_until_checkpoint = aid.checkpoint_period; + last_checkpoint_cpu_time = aid.wu_cpu_time; + time_until_fraction_done_update = aid.fraction_done_update_period; + this_process_active = true; + last_wu_cpu_time = aid.wu_cpu_time; + + set_timer(timer_period); + setup_shared_mem(); + + return 0; +} + + +int boinc_finish(int status) { + double cur_mem; + + boinc_thread_cpu_time(last_checkpoint_cpu_time, cur_mem); + last_checkpoint_cpu_time += aid.wu_cpu_time; + update_app_progress(fraction_done, last_checkpoint_cpu_time, last_checkpoint_cpu_time, cur_mem); +#ifdef _WIN32 + // Stop the timer + timeKillEvent(timer_id); +#endif + cleanup_shared_mem(); + exit(status); + return 0; +} + bool boinc_is_standalone() { return standalone; } + // parse the init data file. // This is done at startup, and also if a "reread prefs" message is received // @@ -126,125 +571,6 @@ int boinc_parse_init_data_file() { } -// Install signal handlers to aid in debugging -// TODO: write Windows equivalent error handlers? -// -int boinc_install_signal_handlers() { -#ifdef HAVE_SIGNAL_H - signal(SIGHUP, boinc_catch_signal); // terminal line hangup - signal(SIGINT, boinc_catch_signal); // interrupt program - signal(SIGQUIT, boinc_quit); // quit program - signal(SIGILL, boinc_catch_signal); // illegal instruction - signal(SIGABRT, boinc_catch_signal); // abort(2) call - signal(SIGBUS, boinc_catch_signal); // bus error - signal(SIGSEGV, boinc_catch_signal); // segmentation violation - signal(SIGSYS, boinc_catch_signal); // system call given invalid argument - signal(SIGPIPE, boinc_catch_signal); // write on a pipe with no reader -#endif -#ifdef _WIN32 - SetUnhandledExceptionFilter(boinc_catch_signal); -#endif - return 0; -} - -#ifdef _WIN32 -LONG CALLBACK boinc_catch_signal(EXCEPTION_POINTERS *pExPtrs) { - - // Snagged from the latest stackwalker code base. This allows us to grab - // callstacks even in a stack overflow scenario - if (pExPtrs->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) - { - static char MyStack[1024*128]; // be sure that we have enought space... - // it assumes that DS and SS are the same!!! (this is the case for Win32) - // change the stack only if the selectors are the same (this is the case for Win32) - //__asm push offset MyStack[1024*128]; - //__asm pop esp; - __asm mov eax,offset MyStack[1024*128]; - __asm mov esp,eax; - } - - PVOID exceptionAddr = pExPtrs->ExceptionRecord->ExceptionAddress; - DWORD exceptionCode = pExPtrs->ExceptionRecord->ExceptionCode; - - LONG lReturnValue = NULL; - char status[256]; - - static long lDetectNestedException = 0; - - // If we've been in this procedure before, something went wrong so we immediately exit - if (InterlockedIncrement(&lDetectNestedException) > 1) { - TerminateProcess(GetCurrentProcess(), ERR_SIGNAL_CATCH); - } - - switch (exceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: safe_strncpy(status,"Access Violation",sizeof(status)); break; - case EXCEPTION_DATATYPE_MISALIGNMENT: safe_strncpy(status,"Data Type Misalignment",sizeof(status)); break; - case EXCEPTION_BREAKPOINT: safe_strncpy(status,"Breakpoint Encountered",sizeof(status)); break; - case EXCEPTION_SINGLE_STEP: safe_strncpy(status,"Single Instruction Executed",sizeof(status)); break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: safe_strncpy(status,"Array Bounds Exceeded",sizeof(status)); break; - case EXCEPTION_FLT_DENORMAL_OPERAND: safe_strncpy(status,"Float Denormal Operand",sizeof(status)); break; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: safe_strncpy(status,"Divide by Zero",sizeof(status)); break; - case EXCEPTION_FLT_INEXACT_RESULT: safe_strncpy(status,"Float Inexact Result",sizeof(status)); break; - case EXCEPTION_FLT_INVALID_OPERATION: safe_strncpy(status,"Float Invalid Operation",sizeof(status)); break; - case EXCEPTION_FLT_OVERFLOW: safe_strncpy(status,"Float Overflow",sizeof(status)); break; - case EXCEPTION_FLT_STACK_CHECK: safe_strncpy(status,"Float Stack Check",sizeof(status)); break; - case EXCEPTION_FLT_UNDERFLOW: safe_strncpy(status,"Float Underflow",sizeof(status)); break; - case EXCEPTION_INT_DIVIDE_BY_ZERO: safe_strncpy(status,"Integer Divide by Zero",sizeof(status)); break; - case EXCEPTION_INT_OVERFLOW: safe_strncpy(status,"Integer Overflow",sizeof(status)); break; - case EXCEPTION_PRIV_INSTRUCTION: safe_strncpy(status,"Privileged Instruction",sizeof(status)); break; - case EXCEPTION_IN_PAGE_ERROR: safe_strncpy(status,"In Page Error",sizeof(status)); break; - case EXCEPTION_ILLEGAL_INSTRUCTION: safe_strncpy(status,"Illegal Instruction",sizeof(status)); break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: safe_strncpy(status,"Noncontinuable Exception",sizeof(status)); break; - case EXCEPTION_STACK_OVERFLOW: safe_strncpy(status,"Stack Overflow",sizeof(status)); break; - case EXCEPTION_INVALID_DISPOSITION: safe_strncpy(status,"Invalid Disposition",sizeof(status)); break; - case EXCEPTION_GUARD_PAGE: safe_strncpy(status,"Guard Page Violation",sizeof(status)); break; - case EXCEPTION_INVALID_HANDLE: safe_strncpy(status,"Invalid Handle",sizeof(status)); break; - case CONTROL_C_EXIT: safe_strncpy(status,"Ctrl+C Exit",sizeof(status)); break; - default: safe_strncpy(status,"Unknown exception",sizeof(status)); break; - } - - fprintf(stderr, "\n***UNHANDLED EXCEPTION****\n"); - fprintf(stderr, "Reason: %s (0x%x) at address 0x%p\n\n", status, exceptionCode, exceptionAddr); - -#ifdef _DEBUG - // Unwind the stack and spew it to stderr - StackwalkFilter(pExPtrs, EXCEPTION_EXECUTE_HANDLER, NULL); -#endif - - fprintf(stderr, "Exiting...\n"); - fflush(stderr); - - // Force terminate the app letting BOINC know an unknown exception has occurred. - TerminateProcess(GetCurrentProcess(), pExPtrs->ExceptionRecord->ExceptionCode); - - // We won't make it to this point, but make the compiler happy anyway. - return 1; -} -#endif - -#ifdef HAVE_SIGNAL_H -void boinc_catch_signal(int signal) { - switch(signal) { - case SIGHUP: fprintf(stderr, "SIGHUP: terminal line hangup"); break; - case SIGINT: fprintf(stderr, "SIGINT: interrupt program"); break; - case SIGILL: fprintf(stderr, "SIGILL: illegal instruction"); break; - case SIGABRT: fprintf(stderr, "SIGABRT: abort called"); break; - case SIGBUS: fprintf(stderr, "SIGBUS: bus error"); break; - case SIGSEGV: fprintf(stderr, "SIGSEGV: segmentation violation"); break; - case SIGSYS: fprintf(stderr, "SIGSYS: system call given invalid argument"); break; - case SIGPIPE: fprintf(stderr, "SIGPIPE: write on a pipe with no reader"); break; - default: fprintf(stderr, "unknown signal %d", signal); break; - } - fprintf(stderr, "\nExiting...\n"); - exit(ERR_SIGNAL_CATCH); -} - -void boinc_quit(int sig) { - signal(SIGQUIT, boinc_quit); // reset signal - time_to_quit = true; -} -#endif - // communicate to the core client (via shared mem) // the current CPU time and fraction done // @@ -459,50 +785,6 @@ static void cleanup_shared_mem() { #endif } -int boinc_init(bool standalone_ /* = false */) { - FILE* f; - int retval; - -#ifdef _WIN32 - DuplicateHandle( - GetCurrentProcess(), - GetCurrentThread(), - GetCurrentProcess(), - &worker_thread_handle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS - ); -#endif - - standalone = standalone_; - - retval = boinc_parse_init_data_file(); - if (retval) return retval; - - // copy the WU CPU time to a separate var, - // since we may reread the structure again later. - // - initial_wu_cpu_time = aid.wu_cpu_time; - - f = boinc_fopen(FD_INIT_FILE, "r"); - if (f) { - parse_fd_init_file(f); - fclose(f); - } - - time_until_checkpoint = aid.checkpoint_period; - last_checkpoint_cpu_time = aid.wu_cpu_time; - time_until_fraction_done_update = aid.fraction_done_update_period; - this_process_active = true; - last_wu_cpu_time = aid.wu_cpu_time; - - boinc_install_signal_handlers(); - set_timer(timer_period); - setup_shared_mem(); - - return 0; -} int boinc_trickle(char* p) { FILE* f = boinc_fopen("trickle", "wb"); @@ -514,20 +796,6 @@ int boinc_trickle(char* p) { return 0; } -int boinc_finish(int status) { - double cur_mem; - - boinc_thread_cpu_time(last_checkpoint_cpu_time, cur_mem); - last_checkpoint_cpu_time += aid.wu_cpu_time; - update_app_progress(fraction_done, last_checkpoint_cpu_time, last_checkpoint_cpu_time, cur_mem); -#ifdef _WIN32 - // Stop the timer - timeKillEvent(timer_id); -#endif - cleanup_shared_mem(); - exit(status); - return 0; -} bool boinc_time_to_checkpoint() { diff --git a/api/boinc_api.h b/api/boinc_api.h index b13247a292..da95050d56 100755 --- a/api/boinc_api.h +++ b/api/boinc_api.h @@ -21,10 +21,77 @@ #define _BOINC_API_ #include -using std::string; +#include + +#ifdef _WIN32 +#include +#endif #include "app_ipc.h" +using std::string; + +// **************************************************************************** +// **************************************************************************** +// +// Diagnostics Support for Windows 95/98/ME/2000/XP/2003 +// +// **************************************************************************** +// **************************************************************************** + +#ifdef _WIN32 + +// +// Define macros for both debug and release builds. +// +// We are using the native debugging technology built into the Microsoft +// C Runtime Libraries to trap and report the asserts and traces. +// + +#ifdef _DEBUG + +// Forward declare so we can assign a macro to it. +void boinc_trace(const char *pszFormat, ...); +void boinc_error_debug(int iExitCode, const char *pszFormat, ...); + +#define BOINCASSERT(expr) _ASSERT_BASE((expr), #expr) +#define BOINCTRACE boinc_trace +#define BOINCERROR boinc_error_debug + +#else // _DEBUG + +// Forward declare so we can assign a macro to it. +void boinc_error_release(int iExitCode, const char *pszFormat, ...); + +#define BOINCASSERT(expr) ((void)0) +#define BOINCTRACE ((void)0) +#define BOINCERROR boinc_error_release + +#endif // _DEBUG + +#endif // _WIN32 + + +// **************************************************************************** +// **************************************************************************** +// +// Diagnostics Support for Undefined Platform +// +// **************************************************************************** +// **************************************************************************** +#ifndef BOINCASSERT +#define BOINCASSERT assert +#endif + +#ifndef BOINCTRACE +#define BOINCTRACE ((int)0) +#endif + +#ifndef BOINCERROR +#define BOINCERROR ((int)0) +#endif + + // MFILE supports a primitive form of checkpointing. // Write all your output (and restart file) to MFILEs. // The output is buffered in memory. @@ -46,24 +113,40 @@ public: long tell() const; }; -extern int boinc_init(bool standalone = false); -extern int boinc_parse_init_data_file(); -extern int boinc_get_init_data(APP_INIT_DATA&); -extern int boinc_trickle(char*); -extern int boinc_finish(int); -extern int boinc_resolve_filename(const char*, char*, int len); -extern int boinc_resolve_filename(const char*, string&); -extern bool boinc_time_to_checkpoint(); -extern int boinc_checkpoint_completed(); -extern int boinc_fraction_done(double); -extern int boinc_child_start(); -extern int boinc_child_done(double); -extern bool boinc_is_standalone(); -extern int boinc_wu_cpu_time(double&); -/////////// API ENDS HERE - IMPLEMENTATION STUFF FOLLOWS +/////////// API BEGINS HERE + +extern int boinc_set_error(int exit_code); + +extern int boinc_init(bool standalone = false); +extern int boinc_finish(int); + +extern bool boinc_is_standalone(); + +extern int boinc_resolve_filename(const char*, char*, int len); +extern int boinc_resolve_filename(const char*, string&); + +extern int boinc_parse_init_data_file(); +extern int boinc_get_init_data(APP_INIT_DATA&); + +extern int boinc_trickle(char*); + +extern bool boinc_time_to_checkpoint(); +extern int boinc_checkpoint_completed(); + +extern int boinc_fraction_done(double); +extern int boinc_child_start(); +extern int boinc_child_done(double); + +extern int boinc_wu_cpu_time(double&); +extern int boinc_thread_cpu_time(double&, double&); + +/////////// API ENDS HERE + +/////////// APPLICATION GLOBALLY DEFINED VARIABLES BEGINS HERE -extern int boinc_thread_cpu_time(double&, double&); extern APP_CLIENT_SHM *app_client_shm; +/////////// APPLICATION GLOBALLY DEFINED VARIABLES ENDS HERE + #endif diff --git a/api/boincdiag.cpp b/api/boincdiag.cpp deleted file mode 100644 index a94fe0223f..0000000000 --- a/api/boincdiag.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// The contents of this file are subject to the BOINC Public License -// Version 1.0 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://boinc.berkeley.edu/license_1.0.txt -// -// Software distributed under the License is distributed on an "AS IS" -// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -// License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// -// The Initial Developer of the Original Code is the SETI@home project. -// Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// -// Contributor(s): -// - -#include "boincdiag.h" - -/////////////////////////////////////////////////////////////////////////////// -// -// Windows 32-bit Platforms -// -/////////////////////////////////////////////////////////////////////////////// -#ifdef _WIN32 - -// Check to see if the MFC/ATL frameworks are included, if so we have to use a -// different set of diagnostics functions. -#ifdef __AFXWIN_H__ - - -// -// TODO: Determine what needs to happen between the two frameworks and implement it -// - - -// Well if we are not using the MFC/ATL frameworks, then we are using the CRT. -#else // __AFXWIN_H__ - -#include -#include -#include -#include "app_ipc.h" - -#ifdef _DEBUG - -void boinc_trace(const char *pszFormat, ...) -{ - static char szBuffer[4096]; - - memset(szBuffer, 0, sizeof(szBuffer)); - - va_list ptr; - va_start(ptr, pszFormat); - - BOINCASSERT( -1 != _vsnprintf(szBuffer, sizeof(szBuffer), pszFormat, ptr) ); - - va_end(ptr); - - _CrtDbgReport(_CRT_WARN, NULL, NULL, NULL, "%s", szBuffer); -} - -#endif // _DEBUG - - -// -// Function: BoincReportingFunction -// -// Purpose: Trap ASSERTs from the CRT and spew them to stderr. -// -// Date: 01/29/04 -// -int __cdecl BoincReportingFunction( int reportType, char *szMsg, int *retVal ){ - (*retVal) = 0; - - if ( _CRT_ASSERT == reportType ){ - fprintf( stderr, "ASSERT: %s\n", szMsg ); - fflush( stderr ); - (*retVal) = 1; - } else { - fprintf( stderr, "TRACE: %s", szMsg ); - fflush( stderr ); - } - - return(TRUE); -} - - -// -// Function: boinc_diag_init -// -// Purpose: Initialize the diagnostic system -// -// Date: 01/29/04 -// -int boinc_diag_init() { - - // Redirect stderr earlier then boinc_init so we can trap errors earlier. - freopen(STDERR_FILE, "a", stderr); - - // Define how messages should me formatted to sdterr - _CrtSetReportHook( BoincReportingFunction ); - - return TRUE; -} - - -// -// Function: boinc_diag_cleanup -// -// Purpose: Cleanup the diagnostic system -// -// Date: 01/29/04 -// -int boinc_diag_cleanup() { - return TRUE; -} - - -#endif // __AFXWIN_H__ - -#endif // _WIN32 diff --git a/api/boincdiag.h b/api/boincdiag.h deleted file mode 100644 index d288449f63..0000000000 --- a/api/boincdiag.h +++ /dev/null @@ -1,121 +0,0 @@ -// The contents of this file are subject to the BOINC Public License -// Version 1.0 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://boinc.berkeley.edu/license_1.0.txt -// -// Software distributed under the License is distributed on an "AS IS" -// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the -// License for the specific language governing rights and limitations -// under the License. -// -// The Original Code is the Berkeley Open Infrastructure for Network Computing. -// -// The Initial Developer of the Original Code is the SETI@home project. -// Portions created by the SETI@home project are Copyright (C) 2002 -// University of California at Berkeley. All Rights Reserved. -// -// Contributor(s): -// - -#ifndef _BOINC_DIAGNOSTICS_ -#define _BOINC_DIAGNOSTICS_ - -/////////////////////////////////////////////////////////////////////////////// -// -// This include file should define the basic debugging infrastructure for -// various boinc applications. -// -// BOINCASSERT should be used to evaluate expressions and spew results to -// sdterr -// -// BOINCTRACE should spew debug information to stderr -// -/////////////////////////////////////////////////////////////////////////////// - - -// -// Diagnostic Function Prototypes -// -int boinc_diag_init(); -int boinc_diag_cleanup(); - - -// Diagnostic functions only available in debug builds -#ifdef _DEBUG - -void boinc_trace(const char *pszFormat, ...); - -#endif - - -/////////////////////////////////////////////////////////////////////////////// -// -// Windows 32-bit Platforms -// -/////////////////////////////////////////////////////////////////////////////// -#ifdef _WIN32 - -// Check to see if the MFC/ATL frameworks are included, if so we have to use a -// different set of diagnostics functions. -#ifdef __AFXWIN_H__ - - -// -// TODO: Determine what needs to happen between the two frameworks and implement it -// - - -// Well if we are not using the MFC/ATL frameworks, then we are using the CRT. -#else // __AFXWIN_H__ - - -// -// Define macros for both debug and release builds. -// -// We are using the native debugging technology built into the Microsoft -// C Runtime Libraries to trap and report the asserts and traces. -// -#include - - - -#ifdef _DEBUG - -#define BOINCASSERT(expr) _ASSERT_BASE((expr), #expr) -#define BOINCTRACE boinc_trace - -#else // _DEBUG - -#define BOINCASSERT(expr) ((void)0) -#define BOINCTRACE ((void)0) - -#endif // _DEBUG - -#endif // __AFXWIN_H__ - -#endif // _WIN32 - - - - -/////////////////////////////////////////////////////////////////////////////// -// -// Undefined Platform/Diagnostic Functions. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef BOINCASSERT - -#include -#define BOINCASSERT assert - -#endif - -#ifndef BOINCTRACE - -#define BOINCTRACE ((int)0) - -#endif - - -#endif //_BOINC_DIAGNOSTICS_ \ No newline at end of file diff --git a/checkin_notes b/checkin_notes index 94665cb8c9..deabf0c79a 100755 --- a/checkin_notes +++ b/checkin_notes @@ -9872,3 +9872,21 @@ Rom Feb 5 2004 boincdiag.cpp api/win/ stackwalker.cpp,h (Added) + +Rom Feb 6 2004 + - Removed boincdiag.cpp,h from build and encorporated all its functionality into + boinc_api.c, h + - Improved unhandled exception filter to handle STACK_OVERFLOW exceptions, using + new stackwalker code base, STACK_OVERFLOWs would have caused a nested + exception issue that would have masked the real error. + - Improved unhandled exception filter to handle ACCESS_VIOLATIONs better, using + stackwalker code base, giving some of the same information for release builds + that is given in debug builds + - Created a new macro called BOINCERROR which will trip the management thread into + gracefully exiting the process with the correct exit code. This macro will work + across debug/release builds. Some more work has to go into the base function, + hopefully in tomorrow. + + api/ + boinc_api.c,h + boincdiag.cpp,h (deleted)