summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2006-08-30 14:02:52 +0000
committerSimon Marlow <simonmar@microsoft.com>2006-08-30 14:02:52 +0000
commitab1e183aa7801f9260a9cbb6edbd553cf8249b25 (patch)
tree7245d178055f0f05ce45c74d8eca56eea49af2b2
parentee4d9a57ab125607e3029a8c1d052114956811f5 (diff)
downloadhaskell-ab1e183aa7801f9260a9cbb6edbd553cf8249b25.tar.gz
add sysErrorBelch() for reporting system call errors
-rw-r--r--includes/RtsMessages.h15
-rw-r--r--rts/MBlock.c9
-rw-r--r--rts/RtsMessages.c73
-rw-r--r--rts/Task.c3
-rw-r--r--rts/posix/GetTime.c2
-rw-r--r--rts/posix/Signals.c6
-rw-r--r--rts/win32/OSThreads.c8
7 files changed, 102 insertions, 14 deletions
diff --git a/includes/RtsMessages.h b/includes/RtsMessages.h
index 63f3ea80c6..79c48d3b98 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 15a4d2300e..9058205716 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 73af8391e9..53a910e756 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 a03ed87651..72147256d8 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 3a0764cb91..89d83a31cb 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 8645f1b826..a5044cd6de 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 00effdaaac..32800e73bd 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;
}