mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
710465235b
commit
1b0b9fcb92
|
|
@ -1,3 +1,23 @@
|
||||||
|
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)
|
||||||
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);
|
||||||
|
|
||||||
/* 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);
|
||||||
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
|
||||||
|
|
||||||
#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
|
||||||
/* 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
|
||||||
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 (msg);
|
||||||
estr_write ("\n");
|
estr_write ("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char errbuf[256];
|
||||||
|
if (state->in_signal_handler)
|
||||||
|
{
|
||||||
|
estr_write (ERRHDR);
|
||||||
|
estr_write (msg);
|
||||||
|
estr_write (", errno: ");
|
||||||
|
const char *p = gfc_itoa (errnum, errbuf, sizeof (errbuf));
|
||||||
|
estr_write (p);
|
||||||
|
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,
|
||||||
/* 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);
|
||||||
void
|
void
|
||||||
backtrace (void)
|
backtrace (void)
|
||||||
{
|
{
|
||||||
show_backtrace (0);
|
show_backtrace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|| (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,
|
||||||
#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
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
/* 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,
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue