add sysErrorBelch() for reporting system call errors
authorSimon Marlow <simonmar@microsoft.com>
Wed, 30 Aug 2006 14:02:52 +0000 (14:02 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Wed, 30 Aug 2006 14:02:52 +0000 (14:02 +0000)
includes/RtsMessages.h
rts/MBlock.c
rts/RtsMessages.c
rts/Task.c
rts/posix/GetTime.c
rts/posix/Signals.c
rts/win32/OSThreads.c

index 63f3ea8..79c48d3 100644 (file)
@@ -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 */
index 15a4d23..9058205 100644 (file)
@@ -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;
index 73af839..53a910e 100644 (file)
@@ -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)
index a03ed87..7214725 100644 (file)
@@ -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);
index 3a0764c..89d83a3 100644 (file)
@@ -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;
index 8645f1b..a5044cd 100644 (file)
@@ -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
 
index 00effda..32800e7 100644 (file)
@@ -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;
 }