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).
extern RtsMsgFunction rtsFatalInternalErrorFn;
extern RtsMsgFunction rtsDebugMsgFn;
extern RtsMsgFunction rtsErrorMsgFn;
+extern RtsMsgFunction rtsSysErrorMsgFn;
#endif /* RTSMESSAGES_H */
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;
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;
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;
RtsMsgFunction *fatalInternalErrorFn = rtsFatalInternalErrorFn;
RtsMsgFunction *debugMsgFn = rtsDebugMsgFn;
RtsMsgFunction *errorMsgFn = rtsErrorMsgFn;
+RtsMsgFunction *sysErrorMsgFn = rtsSysErrorMsgFn;
void
barf(const char*s, ...)
}
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;
#if defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
static int
-isGUIApp()
+isGUIApp(void)
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS pPEHeader;
}
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)
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);
long ticks;
ticks = sysconf(_SC_CLK_TCK);
if ( ticks == -1 ) {
- errorBelch("sysconf\n");
+ sysErrorBelch("sysconf");
stg_exit(EXIT_FAILURE);
}
ClockFreq = ticks;
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)
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
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
NULL); /* unnamed => process-local. */
if ( h == NULL ) {
- errorBelch("initCondition: unable to create");
+ sysErrorBelch("initCondition: unable to create");
+ stg_exit(EXIT_FAILURE);
}
*pCond = h;
return;
closeCondition( Condition* pCond )
{
if ( CloseHandle(*pCond) == 0 ) {
- errorBelch("closeCondition: failed to close");
+ sysErrorBelch("closeCondition: failed to close");
}
return;
}
signalCondition ( Condition* pCond )
{
if (SetEvent(*pCond) == 0) {
- barf("SetEvent: %d", GetLastError());
+ sysErrorBelch("SetEvent");
+ stg_exit(EXIT_FAILURE);
}
return rtsTrue;
}