Commit 1b0b9fcb by Janne Blomqvist

PR 67414 Better diagnostics on backtrace failure, gf_strerror bugfix

2015-09-02  Janne Blomqvist  <jb@gcc.gnu.org>

	PR libfortran/67414
	* io/write.c (gfc_itoa): Move to runtime/string.c.
	* libgfortran.h (show_backtrace): Make arg bool.
	(gfc_itoa): New prototype.
	* runtime/backtrace.c (struct mystate): Change type of try_simple
	field, add in_signal_handler field.
	(error_callback): Print out error number, or if not in a signal
	handler, the error message.
	(show_backtrace): Change type of arg, change initialization of
	struct mystate.
	(backtrace): Call show_backtrace with correct arg type.
	* runtime/compile_options.c (backtrace_handler): Call with correct
	arg type.
	* runtime/error.c (sys_abort): Likewise.
	(gf_strerror): Handle newlocale() failure.
	* runtime/string.c (gfc_itoa): Function moved here from
	io/write.c.

From-SVN: r227404
parent 71046523
2015-09-02 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/67414
* io/write.c (gfc_itoa): Move to runtime/string.c.
* libgfortran.h (show_backtrace): Make arg bool.
(gfc_itoa): New prototype.
* runtime/backtrace.c (struct mystate): Change type of try_simple
field, add in_signal_handler field.
(error_callback): Print out error number, or if not in a signal
handler, the error message.
(show_backtrace): Change type of arg, change initialization of
struct mystate.
(backtrace): Call show_backtrace with correct arg type.
* runtime/compile_options.c (backtrace_handler): Call with correct
arg type.
* runtime/error.c (sys_abort): Likewise.
(gf_strerror): Handle newlocale() failure.
* runtime/string.c (gfc_itoa): Function moved here from
io/write.c.
2015-08-31 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> 2015-08-31 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
PR libfortran/47571 PR libfortran/47571
......
...@@ -1032,47 +1032,6 @@ ztoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n) ...@@ -1032,47 +1032,6 @@ ztoa_big (const char *s, char *buffer, int len, GFC_UINTEGER_LARGEST *n)
return buffer; return buffer;
} }
/* gfc_itoa()-- Integer to decimal conversion.
The itoa function is a widespread non-standard extension to standard
C, often declared in <stdlib.h>. Even though the itoa defined here
is a static function we take care not to conflict with any prior
non-static declaration. Hence the 'gfc_' prefix, which is normally
reserved for functions with external linkage. */
static const char *
gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
{
int negative;
char *p;
GFC_UINTEGER_LARGEST t;
assert (len >= GFC_ITOA_BUF_SIZE);
if (n == 0)
return "0";
negative = 0;
t = n;
if (n < 0)
{
negative = 1;
t = -n; /*must use unsigned to protect from overflow*/
}
p = buffer + GFC_ITOA_BUF_SIZE - 1;
*p = '\0';
while (t != 0)
{
*--p = '0' + (t % 10);
t /= 10;
}
if (negative)
*--p = '-';
return p;
}
void void
write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len) write_i (st_parameter_dt *dtp, const fnode *f, const char *p, int len)
......
...@@ -651,7 +651,7 @@ export_proto(store_exe_path); ...@@ -651,7 +651,7 @@ export_proto(store_exe_path);
/* backtrace.c */ /* backtrace.c */
extern void show_backtrace (int); extern void show_backtrace (bool);
internal_proto(show_backtrace); internal_proto(show_backtrace);
...@@ -838,6 +838,9 @@ internal_proto(fc_strdup); ...@@ -838,6 +838,9 @@ internal_proto(fc_strdup);
extern char *fc_strdup_notrim(const char *, gfc_charlen_type); extern char *fc_strdup_notrim(const char *, gfc_charlen_type);
internal_proto(fc_strdup_notrim); internal_proto(fc_strdup_notrim);
extern const char *gfc_itoa(GFC_INTEGER_LARGEST, char *, size_t);
internal_proto(gfc_itoa);
/* io/intrinsics.c */ /* io/intrinsics.c */
extern void flush_all_units (void); extern void flush_all_units (void);
......
...@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
...@@ -38,8 +39,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -38,8 +39,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* Store our own state while backtracing. */ /* Store our own state while backtracing. */
struct mystate struct mystate
{ {
int try_simple;
int frame; int frame;
bool try_simple;
bool in_signal_handler;
}; };
...@@ -65,15 +67,35 @@ static void ...@@ -65,15 +67,35 @@ static void
error_callback (void *data, const char *msg, int errnum) error_callback (void *data, const char *msg, int errnum)
{ {
struct mystate *state = (struct mystate *) data; struct mystate *state = (struct mystate *) data;
#define ERRHDR "\nCould not print backtrace: "
if (errnum < 0) if (errnum < 0)
{ {
state->try_simple = 1; state->try_simple = true;
return; return;
} }
else if (errnum == 0)
estr_write ("\nSomething went wrong while printing the backtrace: "); {
estr_write (ERRHDR);
estr_write (msg);
estr_write ("\n");
}
else
{
char errbuf[256];
if (state->in_signal_handler)
{
estr_write (ERRHDR);
estr_write (msg); estr_write (msg);
estr_write (", errno: ");
const char *p = gfc_itoa (errnum, errbuf, sizeof (errbuf));
estr_write (p);
estr_write ("\n"); estr_write ("\n");
}
else
st_printf (ERRHDR "%s: %s\n", msg,
gf_strerror (errnum, errbuf, sizeof (errbuf)));
}
} }
static int static int
...@@ -110,10 +132,10 @@ full_callback (void *data, uintptr_t pc, const char *filename, ...@@ -110,10 +132,10 @@ full_callback (void *data, uintptr_t pc, const char *filename,
/* Display the backtrace. */ /* Display the backtrace. */
void void
show_backtrace (int in_signal_handler) show_backtrace (bool in_signal_handler)
{ {
struct backtrace_state *lbstate; struct backtrace_state *lbstate;
struct mystate state = { 0, 0 }; struct mystate state = { 0, false, in_signal_handler };
lbstate = backtrace_create_state (NULL, 1, error_callback, NULL); lbstate = backtrace_create_state (NULL, 1, error_callback, NULL);
...@@ -147,6 +169,6 @@ export_proto (backtrace); ...@@ -147,6 +169,6 @@ export_proto (backtrace);
void void
backtrace (void) backtrace (void)
{ {
show_backtrace (0); show_backtrace (false);
} }
...@@ -126,7 +126,7 @@ backtrace_handler (int signum) ...@@ -126,7 +126,7 @@ backtrace_handler (int signum)
show_signal (signum); show_signal (signum);
estr_write ("\nBacktrace for this error:\n"); estr_write ("\nBacktrace for this error:\n");
show_backtrace (1); show_backtrace (true);
/* Now reraise the signal. We reactivate the signal's /* Now reraise the signal. We reactivate the signal's
default handling, which is to terminate the process. default handling, which is to terminate the process.
......
...@@ -173,7 +173,7 @@ sys_abort (void) ...@@ -173,7 +173,7 @@ sys_abort (void)
|| (options.backtrace == -1 && compile_options.backtrace == 1)) || (options.backtrace == -1 && compile_options.backtrace == 1))
{ {
estr_write ("\nProgram aborted. Backtrace:\n"); estr_write ("\nProgram aborted. Backtrace:\n");
show_backtrace (0); show_backtrace (false);
signal (SIGABRT, SIG_DFL); signal (SIGABRT, SIG_DFL);
} }
...@@ -221,8 +221,16 @@ gf_strerror (int errnum, ...@@ -221,8 +221,16 @@ gf_strerror (int errnum,
#ifdef HAVE_STRERROR_L #ifdef HAVE_STRERROR_L
locale_t myloc = newlocale (LC_CTYPE_MASK | LC_MESSAGES_MASK, "", locale_t myloc = newlocale (LC_CTYPE_MASK | LC_MESSAGES_MASK, "",
(locale_t) 0); (locale_t) 0);
char *p = strerror_l (errnum, myloc); char *p;
if (myloc)
{
p = strerror_l (errnum, myloc);
freelocale (myloc); freelocale (myloc);
}
else
/* newlocale might fail e.g. due to running out of memory, fall
back to the simpler strerror. */
p = strerror (errnum);
return p; return p;
#elif defined(HAVE_STRERROR_R) #elif defined(HAVE_STRERROR_R)
#ifdef HAVE_USELOCALE #ifdef HAVE_USELOCALE
......
/* Copyright (C) 2002-2015 Free Software Foundation, Inc. /* Copyright (C) 2002-2015 Free Software Foundation, Inc.
Contributed by Paul Brook Contributed by Paul Brook
This file is part of the GNU Fortran 95 runtime library (libgfortran). This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or modify Libgfortran is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
...@@ -167,3 +167,48 @@ find_option (st_parameter_common *cmp, const char *s1, gfc_charlen_type s1_len, ...@@ -167,3 +167,48 @@ find_option (st_parameter_common *cmp, const char *s1, gfc_charlen_type s1_len,
return -1; return -1;
} }
/* gfc_itoa()-- Integer to decimal conversion.
The itoa function is a widespread non-standard extension to
standard C, often declared in <stdlib.h>. Even though the itoa
defined here is a static function we take care not to conflict with
any prior non-static declaration. Hence the 'gfc_' prefix, which
is normally reserved for functions with external linkage. Notably,
in contrast to the *printf() family of functions, this ought to be
async-signal-safe. */
const char *
gfc_itoa (GFC_INTEGER_LARGEST n, char *buffer, size_t len)
{
int negative;
char *p;
GFC_UINTEGER_LARGEST t;
if (len < GFC_ITOA_BUF_SIZE)
sys_abort ();
if (n == 0)
return "0";
negative = 0;
t = n;
if (n < 0)
{
negative = 1;
t = -n; /*must use unsigned to protect from overflow*/
}
p = buffer + GFC_ITOA_BUF_SIZE - 1;
*p = '\0';
while (t != 0)
{
*--p = '0' + (t % 10);
t /= 10;
}
if (negative)
*--p = '-';
return p;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment