From ab1e183aa7801f9260a9cbb6edbd553cf8249b25 Mon Sep 17 00:00:00 2001 From: Simon Marlow Date: Wed, 30 Aug 2006 14:02:52 +0000 Subject: [PATCH] add sysErrorBelch() for reporting system call errors --- includes/RtsMessages.h | 15 ++++++++++ rts/MBlock.c | 9 +++--- rts/RtsMessages.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++- rts/Task.c | 3 +- rts/posix/GetTime.c | 2 +- rts/posix/Signals.c | 6 ++-- rts/win32/OSThreads.c | 8 ++++-- 7 files changed, 102 insertions(+), 14 deletions(-) diff --git a/includes/RtsMessages.h b/includes/RtsMessages.h index 63f3ea8..79c48d3 100644 --- a/includes/RtsMessages.h +++ b/includes/RtsMessages.h @@ -47,6 +47,20 @@ extern void errorBelch(const char *s, ...) extern void verrorBelch(const char *s, va_list ap); /* + * An error condition which is caused by and/or can be corrected by + * the user, and which has an associated error condition reported + * by the system (in errno on Unix, and GetLastError() on Windows). + * The system error message is appended to the message generated + * from the supplied format string. + * + * sysErrorBelch() invokes (*sysErrorMsgFn)(). + */ +extern void sysErrorBelch(const char *s, ...) + GNUC3_ATTRIBUTE(format (printf, 1, 2)); + +extern void vsysErrorBelch(const char *s, va_list ap); + +/* * A debugging message. Debugging messages are generated either as a * virtue of having DEBUG turned on, or by being explicitly selected * via RTS options (eg. +RTS -Ds). @@ -72,5 +86,6 @@ extern RtsMsgFunction *errorMsgFn; extern RtsMsgFunction rtsFatalInternalErrorFn; extern RtsMsgFunction rtsDebugMsgFn; extern RtsMsgFunction rtsErrorMsgFn; +extern RtsMsgFunction rtsSysErrorMsgFn; #endif /* RTSMESSAGES_H */ diff --git a/rts/MBlock.c b/rts/MBlock.c index 15a4d23..9058205 100644 --- a/rts/MBlock.c +++ b/rts/MBlock.c @@ -337,9 +337,8 @@ allocNew(nat n) { if(rec->base==0) { stgFree((void*)rec); rec=0; - errorBelch( - "getMBlocks: VirtualAlloc MEM_RESERVE %d blocks failed with: %ld\n" - , n, GetLastError()); + sysErrorBelch( + "getMBlocks: VirtualAlloc MEM_RESERVE %d blocks failed", n); } else { if(allocs==0) { allocs=rec; @@ -451,7 +450,7 @@ commitBlocks(char* base, int size) { if(size_delta>size) size_delta=size; temp = VirtualAlloc(base, size_delta, MEM_COMMIT, PAGE_READWRITE); if(temp==0) { - errorBelch("getMBlocks: VirtualAlloc MEM_COMMIT failed: %ld\n", GetLastError()); + sysErrorBelch("getMBlocks: VirtualAlloc MEM_COMMIT failed"); stg_exit(EXIT_FAILURE); } size-=size_delta; @@ -515,7 +514,7 @@ freeAllMBlocks(void) it=allocs; for(; it!=0; ) { if(!VirtualFree((void*)it->base, 0, MEM_RELEASE)) { - errorBelch("freeAllMBlocks: VirtualFree MEM_RELEASE failed with %ld", GetLastError()); + sysErrorBelch("freeAllMBlocks: VirtualFree MEM_RELEASE failed"); stg_exit(EXIT_FAILURE); } next = it->next; diff --git a/rts/RtsMessages.c b/rts/RtsMessages.c index 73af839..53a910e 100644 --- a/rts/RtsMessages.c +++ b/rts/RtsMessages.c @@ -28,6 +28,7 @@ RtsMsgFunction *fatalInternalErrorFn = rtsFatalInternalErrorFn; RtsMsgFunction *debugMsgFn = rtsDebugMsgFn; RtsMsgFunction *errorMsgFn = rtsErrorMsgFn; +RtsMsgFunction *sysErrorMsgFn = rtsSysErrorMsgFn; void barf(const char*s, ...) @@ -68,6 +69,21 @@ verrorBelch(const char*s, va_list ap) } void +sysErrorBelch(const char*s, ...) +{ + va_list ap; + va_start(ap,s); + (*sysErrorMsgFn)(s,ap); + va_end(ap); +} + +void +vsysErrorBelch(const char*s, va_list ap) +{ + (*sysErrorMsgFn)(s,ap); +} + +void debugBelch(const char*s, ...) { va_list ap; @@ -90,7 +106,7 @@ vdebugBelch(const char*s, va_list ap) #if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) static int -isGUIApp() +isGUIApp(void) { PIMAGE_DOS_HEADER pDOSHeader; PIMAGE_NT_HEADERS pPEHeader; @@ -178,6 +194,61 @@ rtsErrorMsgFn(const char *s, va_list ap) } void +rtsSysErrorMsgFn(const char *s, va_list ap) +{ + char *syserr; + +#if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR) &syserr, + 0, + NULL ); + + if (isGUIApp()) + { + char buf[BUFSIZE]; + int r; + + r = vsnprintf(buf, BUFSIZE, s, ap); + if (r > 0 && r < BUFSIZE) { + r = vsnprintf(buf+r, BUFSIZE-r, ": %s", syserr); + MessageBox(NULL /* hWnd */, + buf, + prog_name, + MB_OK | MB_ICONERROR | MB_TASKMODAL + ); + } + } + else +#else + syserr = strerror(errno); + // ToDo: use strerror_r() if available +#endif + { + /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ + if (prog_argv != NULL && prog_name != NULL) { + fprintf(stderr, "%s: ", prog_name); + } + vfprintf(stderr, s, ap); + if (syserr) { + fprintf(stderr, ": %s\n", syserr); + } else { + fprintf(stderr, "\n"); + } + } + +#if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) + if (syserr) LocalFree(syserr); +#endif +} + +void rtsDebugMsgFn(const char *s, va_list ap) { #if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) diff --git a/rts/Task.c b/rts/Task.c index a03ed87..7214725 100644 --- a/rts/Task.c +++ b/rts/Task.c @@ -283,7 +283,8 @@ startWorkerTask (Capability *cap, r = createOSThread(&tid, (OSThreadProc *)taskStart, task); if (r != 0) { - barf("startTask: Can't create new task"); + sysErrorBelch("failed to create OS thread"); + stg_exit(EXIT_FAILURE); } debugTrace(DEBUG_sched, "new worker task (taskCount: %d)", taskCount); diff --git a/rts/posix/GetTime.c b/rts/posix/GetTime.c index 3a0764c..89d83a3 100644 --- a/rts/posix/GetTime.c +++ b/rts/posix/GetTime.c @@ -89,7 +89,7 @@ void getProcessTimes(Ticks *user, Ticks *elapsed) long ticks; ticks = sysconf(_SC_CLK_TCK); if ( ticks == -1 ) { - errorBelch("sysconf\n"); + sysErrorBelch("sysconf"); stg_exit(EXIT_FAILURE); } ClockFreq = ticks; diff --git a/rts/posix/Signals.c b/rts/posix/Signals.c index 8645f1b..a5044cd 100644 --- a/rts/posix/Signals.c +++ b/rts/posix/Signals.c @@ -506,7 +506,7 @@ initDefaultHandlers() sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGINT, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGINT handler"); + sysErrorBelch("warning: failed to install SIGINT handler"); } #if defined(HAVE_SIGINTERRUPT) @@ -518,7 +518,7 @@ initDefaultHandlers() sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGCONT, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGCONT handler"); + sysErrorBelch("warning: failed to install SIGCONT handler"); } // install the SIGFPE handler @@ -536,7 +536,7 @@ initDefaultHandlers() sigemptyset(&action.sa_mask); action.sa_flags = 0; if (sigaction(SIGFPE, &action, &oact) != 0) { - errorBelch("warning: failed to install SIGFPE handler"); + sysErrorBelch("warning: failed to install SIGFPE handler"); } #endif diff --git a/rts/win32/OSThreads.c b/rts/win32/OSThreads.c index 00effda..32800e7 100644 --- a/rts/win32/OSThreads.c +++ b/rts/win32/OSThreads.c @@ -38,7 +38,8 @@ initCondition( Condition* pCond ) NULL); /* unnamed => process-local. */ if ( h == NULL ) { - errorBelch("initCondition: unable to create"); + sysErrorBelch("initCondition: unable to create"); + stg_exit(EXIT_FAILURE); } *pCond = h; return; @@ -48,7 +49,7 @@ void closeCondition( Condition* pCond ) { if ( CloseHandle(*pCond) == 0 ) { - errorBelch("closeCondition: failed to close"); + sysErrorBelch("closeCondition: failed to close"); } return; } @@ -64,7 +65,8 @@ rtsBool signalCondition ( Condition* pCond ) { if (SetEvent(*pCond) == 0) { - barf("SetEvent: %d", GetLastError()); + sysErrorBelch("SetEvent"); + stg_exit(EXIT_FAILURE); } return rtsTrue; } -- 1.7.10.4