mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
[svn] Logging system bugfixes and improvements.
Published in <sxsofl7vdyo.fsf@florida.arsdigita.de>.
This commit is contained in:
parent
7d65f1b896
commit
1365950c01
@ -1,3 +1,34 @@
|
||||
2001-12-10 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||
|
||||
* main.c (main): Initialize progress after fork_to_background, so
|
||||
that it knows when to use dots.
|
||||
|
||||
* mswindows.c (ws_hangup): Call log_request_redirect_output.
|
||||
|
||||
* utils.c (fork_to_background): Print the PID of the child
|
||||
process.
|
||||
|
||||
* log.c (log_request_redirect_output): Set a flag that output
|
||||
redirection has been requested. Doing anything else in a signal
|
||||
handler is unsafe.
|
||||
(check_redirect_output): New function: check whether redirection
|
||||
has been requested and, if so, call redirect_output().
|
||||
(logputs): Call check_redirect_output.
|
||||
(logprintf): Ditto.
|
||||
(debug_logprintf): Ditto.
|
||||
(redirect_output): Print clearer messages.
|
||||
|
||||
* main.c (redirect_output_signal): Don't call
|
||||
redirect_output_signal directly. Instead, call
|
||||
log_request_redirect_output.
|
||||
|
||||
* utils.c (memfatal): Ditto.
|
||||
|
||||
* progress.c (display_image): Use it.
|
||||
|
||||
* log.c (log_set_save_context): New function: allow the caller to
|
||||
turn off saving log context lines.
|
||||
|
||||
2001-12-10 Hrvoje Niksic <hniksic@arsdigita.com>
|
||||
|
||||
* host.c (address_list_set_faulty): Uncomment a sanity check.
|
||||
|
199
src/log.c
199
src/log.c
@ -44,16 +44,43 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
/* The file descriptor used for logging. */
|
||||
|
||||
/* This file impplement support for "logging". Logging means printing
|
||||
output, plus several additional features:
|
||||
|
||||
- Cataloguing output by importance. You can specify that a log
|
||||
message is "verbose" or "debug", and it will not be printed unless
|
||||
in verbose or debug mode, respectively.
|
||||
|
||||
- Redirecting the log to the file. When Wget's output goes to the
|
||||
terminal, and Wget receives SIGHUP, all further output is
|
||||
redirected to a log file. When this is the case, Wget can also
|
||||
print the last several lines of "context" to the log file so that
|
||||
it does not begin in the middle of a line. For this to work, the
|
||||
logging code stores the last several lines of context. Callers may
|
||||
request for certain output not to be stored.
|
||||
|
||||
- Inhibiting output. When Wget receives SIGHUP, but redirecting
|
||||
the output fails, logging is inhibited. */
|
||||
|
||||
|
||||
/* The file descriptor used for logging. This is NULL before log_init
|
||||
is called; logging functions log to stderr then. log_init sets it
|
||||
either to stderr or to a file pointer obtained from fopen(). If
|
||||
logging is inhibited, logfp is set back to NULL. */
|
||||
static FILE *logfp;
|
||||
|
||||
/* Whether logging is saved at all. */
|
||||
int save_log_p;
|
||||
/* If non-zero, it means logging is inhibited, i.e. nothing is printed
|
||||
or stored. */
|
||||
static int inhibit_logging;
|
||||
|
||||
/* Whether the last output lines are stored for use as context. */
|
||||
static int save_context_p;
|
||||
|
||||
/* Whether the log is flushed after each command. */
|
||||
static int flush_log_p = 1;
|
||||
|
||||
/* Whether any output has been received while flush_log_p was 0. */
|
||||
static int needs_flushing;
|
||||
|
||||
/* In the event of a hang-up, and if its output was on a TTY, Wget
|
||||
@ -72,13 +99,13 @@ static int needs_flushing;
|
||||
The problem here is that we'd have to either (re)allocate and free
|
||||
strings all the time, or limit the lines to an arbitrary number of
|
||||
characters. Instead of settling for either of these, we do both:
|
||||
if the line is smaller than a certain "usual" line length (80 chars
|
||||
by default), a preallocated memory is used. The rare lines that
|
||||
are longer than 80 characters are malloc'ed and freed separately.
|
||||
This gives good performance with minimum memory consumption and
|
||||
fragmentation. */
|
||||
if the line is smaller than a certain "usual" line length (128
|
||||
chars by default), a preallocated memory is used. The rare lines
|
||||
that are longer than 128 characters are malloc'ed and freed
|
||||
separately. This gives good performance with minimum memory
|
||||
consumption and fragmentation. */
|
||||
|
||||
#define STATIC_LENGTH 80
|
||||
#define STATIC_LENGTH 128
|
||||
|
||||
static struct log_ln {
|
||||
char static_line[STATIC_LENGTH + 1]; /* statically allocated
|
||||
@ -100,6 +127,7 @@ static int log_line_current = -1;
|
||||
than create new ones. */
|
||||
static int trailing_line;
|
||||
|
||||
static void check_redirect_output PARAMS ((void));
|
||||
|
||||
#define ROT_ADVANCE(num) do { \
|
||||
if (++num >= SAVED_LOG_LINES) \
|
||||
@ -252,15 +280,21 @@ saved_append (const char *s)
|
||||
return; \
|
||||
}
|
||||
|
||||
#define CANONICALIZE_LOGFP_OR_RETURN do { \
|
||||
if (logfp == stdin) \
|
||||
return; \
|
||||
else if (!logfp) \
|
||||
/* This might happen if somebody calls a */ \
|
||||
/* log* function before log_init(). */ \
|
||||
logfp = stderr; \
|
||||
} while (0)
|
||||
/* Returns the file descriptor for logging. This is LOGFP, except if
|
||||
called before log_init, in which case it returns stderr. This is
|
||||
useful in case someone calls a logging function before log_init.
|
||||
|
||||
If logging is inhibited, return NULL. */
|
||||
|
||||
static FILE *
|
||||
get_log_fp (void)
|
||||
{
|
||||
if (inhibit_logging)
|
||||
return NULL;
|
||||
if (logfp)
|
||||
return logfp;
|
||||
return stderr;
|
||||
}
|
||||
|
||||
/* Log a literal string S. The string is logged as-is, without a
|
||||
newline appended. */
|
||||
@ -268,13 +302,15 @@ saved_append (const char *s)
|
||||
void
|
||||
logputs (enum log_options o, const char *s)
|
||||
{
|
||||
CHECK_VERBOSE (o);
|
||||
CANONICALIZE_LOGFP_OR_RETURN;
|
||||
FILE *fp;
|
||||
|
||||
fputs (s, logfp);
|
||||
if (save_log_p)
|
||||
check_redirect_output ();
|
||||
if (!(fp = get_log_fp ()))
|
||||
return;
|
||||
|
||||
fputs (s, fp);
|
||||
if (save_context_p)
|
||||
saved_append (s);
|
||||
|
||||
if (flush_log_p)
|
||||
logflush ();
|
||||
else
|
||||
@ -288,7 +324,7 @@ struct logvprintf_state {
|
||||
};
|
||||
|
||||
/* Print a message to the log. A copy of message will be saved to
|
||||
saved_log, for later reusal by log_dump().
|
||||
saved_log, for later reusal by log_dump_context().
|
||||
|
||||
It is not possible to code this function in a "natural" way, using
|
||||
a loop, because of the braindeadness of the varargs API.
|
||||
@ -304,12 +340,13 @@ logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
|
||||
char *write_ptr = smallmsg;
|
||||
int available_size = sizeof (smallmsg);
|
||||
int numwritten;
|
||||
FILE *fp = get_log_fp ();
|
||||
|
||||
if (!save_log_p)
|
||||
if (!save_context_p)
|
||||
{
|
||||
/* In the simple case just call vfprintf(), to avoid needless
|
||||
allocation and games with vsnprintf(). */
|
||||
vfprintf (logfp, fmt, args);
|
||||
vfprintf (fp, fmt, args);
|
||||
goto flush;
|
||||
}
|
||||
|
||||
@ -356,7 +393,7 @@ logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
|
||||
|
||||
/* Writing succeeded. */
|
||||
saved_append (write_ptr);
|
||||
fputs (write_ptr, logfp);
|
||||
fputs (write_ptr, fp);
|
||||
if (state->bigmsg)
|
||||
xfree (state->bigmsg);
|
||||
|
||||
@ -373,8 +410,9 @@ logvprintf (struct logvprintf_state *state, const char *fmt, va_list args)
|
||||
void
|
||||
logflush (void)
|
||||
{
|
||||
CANONICALIZE_LOGFP_OR_RETURN;
|
||||
fflush (logfp);
|
||||
FILE *fp = get_log_fp ();
|
||||
if (fp)
|
||||
fflush (fp);
|
||||
needs_flushing = 0;
|
||||
}
|
||||
|
||||
@ -400,6 +438,18 @@ log_set_flush (int flush)
|
||||
}
|
||||
}
|
||||
|
||||
/* (Temporarily) disable storing log to memory. Returns the old
|
||||
status of storing, with which this function can be called again to
|
||||
reestablish storing. */
|
||||
|
||||
int
|
||||
log_set_save_context (int savep)
|
||||
{
|
||||
int old = save_context_p;
|
||||
save_context_p = savep;
|
||||
return old;
|
||||
}
|
||||
|
||||
#ifdef WGET_USE_STDARG
|
||||
# define VA_START_1(arg1_type, arg1, args) va_start(args, arg1)
|
||||
# define VA_START_2(arg1_type, arg1, arg2_type, arg2, args) va_start(args, arg2)
|
||||
@ -440,8 +490,10 @@ logprintf (va_alist)
|
||||
va_end (args);
|
||||
#endif
|
||||
|
||||
check_redirect_output ();
|
||||
if (inhibit_logging)
|
||||
return;
|
||||
CHECK_VERBOSE (o);
|
||||
CANONICALIZE_LOGFP_OR_RETURN;
|
||||
|
||||
memset (&lpstate, '\0', sizeof (lpstate));
|
||||
do
|
||||
@ -474,7 +526,9 @@ debug_logprintf (va_alist)
|
||||
struct logvprintf_state lpstate;
|
||||
int done;
|
||||
|
||||
CANONICALIZE_LOGFP_OR_RETURN;
|
||||
check_redirect_output ();
|
||||
if (inhibit_logging)
|
||||
return;
|
||||
|
||||
memset (&lpstate, '\0', sizeof (lpstate));
|
||||
do
|
||||
@ -512,7 +566,7 @@ log_init (const char *file, int appendp)
|
||||
easier on the user. */
|
||||
logfp = stderr;
|
||||
|
||||
/* If the output is a TTY, enable logging, which will make Wget
|
||||
/* If the output is a TTY, enable storing, which will make Wget
|
||||
remember all the printed messages, to be able to dump them to
|
||||
a log file in case SIGHUP or SIGUSR1 is received (or
|
||||
Ctrl+Break is pressed under Windows). */
|
||||
@ -522,7 +576,7 @@ log_init (const char *file, int appendp)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
save_log_p = 1;
|
||||
save_context_p = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,9 +588,12 @@ log_close (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (logfp != stdin)
|
||||
if (logfp)
|
||||
fclose (logfp);
|
||||
save_log_p = 0;
|
||||
logfp = NULL;
|
||||
inhibit_logging = 1;
|
||||
save_context_p = 0;
|
||||
|
||||
for (i = 0; i < SAVED_LOG_LINES; i++)
|
||||
free_log_line (i);
|
||||
log_line_current = -1;
|
||||
@ -545,10 +602,12 @@ log_close (void)
|
||||
|
||||
/* Dump saved lines to logfp. */
|
||||
static void
|
||||
log_dump (void)
|
||||
log_dump_context (void)
|
||||
{
|
||||
int num = log_line_current;
|
||||
FILE *fp = logfp;
|
||||
FILE *fp = get_log_fp ();
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
if (num == -1)
|
||||
return;
|
||||
@ -567,33 +626,61 @@ log_dump (void)
|
||||
fputs (log_lines[log_line_current].content, fp);
|
||||
fflush (fp);
|
||||
}
|
||||
|
||||
/* When SIGHUP or SIGUSR1 are received, the output is redirected
|
||||
elsewhere. Such redirection is only allowed once. */
|
||||
enum { RR_NONE, RR_REQUESTED, RR_DONE } redirect_request = RR_NONE;
|
||||
static const char *redirect_request_signal_name;
|
||||
|
||||
/* Redirect output to `wget-log'. MESSIJ is printed on stdout, and
|
||||
should contain *exactly one* `%s', which will be replaced by the
|
||||
log file name.
|
||||
/* Redirect output to `wget-log'. */
|
||||
|
||||
If logging was not enabled, MESSIJ will not be printed. */
|
||||
void
|
||||
redirect_output (const char *messij)
|
||||
static void
|
||||
redirect_output (void)
|
||||
{
|
||||
char *logfile;
|
||||
|
||||
if (!save_log_p)
|
||||
return;
|
||||
|
||||
logfile = unique_name (DEFAULT_LOGFILE);
|
||||
char *logfile = unique_name (DEFAULT_LOGFILE);
|
||||
fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"),
|
||||
redirect_request_signal_name, logfile);
|
||||
logfp = fopen (logfile, "w");
|
||||
if (!logfp)
|
||||
{
|
||||
/* Eek! Opening the alternate log file has failed. Nothing we
|
||||
can do but disable printing completely. */
|
||||
fprintf (stderr, "%s: %s: %s\n", exec_name, logfile, strerror (errno));
|
||||
/* `stdin' is magic to not print anything, ever. */
|
||||
logfp = stdin;
|
||||
fprintf (stderr, _("%s: %s; disabling logging.\n"),
|
||||
logfile, strerror (errno));
|
||||
inhibit_logging = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Dump the context output to the newly opened log. */
|
||||
log_dump_context ();
|
||||
}
|
||||
fprintf (stderr, messij, logfile);
|
||||
xfree (logfile);
|
||||
/* Dump the previous screenful of output to LOGFILE. */
|
||||
log_dump ();
|
||||
save_log_p = 0;
|
||||
save_context_p = 0;
|
||||
}
|
||||
|
||||
/* Check whether a signal handler requested the output to be
|
||||
redirected. */
|
||||
|
||||
static void
|
||||
check_redirect_output (void)
|
||||
{
|
||||
if (redirect_request == RR_REQUESTED)
|
||||
{
|
||||
redirect_request = RR_DONE;
|
||||
redirect_output ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Request redirection at a convenient time. This may be called from
|
||||
a signal handler. */
|
||||
|
||||
void
|
||||
log_request_redirect_output (const char *signal_name)
|
||||
{
|
||||
if (redirect_request == RR_NONE && save_context_p)
|
||||
/* Request output redirection. The request will be processed by
|
||||
check_redirect_output(), which is called from entry point log
|
||||
functions. */
|
||||
redirect_request = RR_REQUESTED;
|
||||
redirect_request_signal_name = signal_name;
|
||||
}
|
||||
|
26
src/main.c
26
src/main.c
@ -75,7 +75,7 @@ struct options opt;
|
||||
/* From log.c. */
|
||||
void log_init PARAMS ((const char *, int));
|
||||
void log_close PARAMS ((void));
|
||||
void redirect_output PARAMS ((const char *));
|
||||
void log_request_redirect_output PARAMS ((const char *));
|
||||
|
||||
static RETSIGTYPE redirect_output_signal PARAMS ((int));
|
||||
|
||||
@ -679,11 +679,6 @@ GNU General Public License for more details.\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize progress. Have to do this after the options are
|
||||
processed so we know where the log file is. */
|
||||
if (opt.verbose)
|
||||
set_progress_implementation (opt.progress_type);
|
||||
|
||||
/* All user options have now been processed, so it's now safe to do
|
||||
interoption dependency checks. */
|
||||
|
||||
@ -731,6 +726,11 @@ Can't timestamp and not clobber old files at the same time.\n"));
|
||||
if (opt.background)
|
||||
fork_to_background ();
|
||||
|
||||
/* Initialize progress. Have to do this after the options are
|
||||
processed so we know where the log file is. */
|
||||
if (opt.verbose)
|
||||
set_progress_implementation (opt.progress_type);
|
||||
|
||||
/* Allocate basic pointer. */
|
||||
url = ALLOCA_ARRAY (char *, nurl + 1);
|
||||
/* Fill in the arguments. */
|
||||
@ -886,15 +886,11 @@ Can't timestamp and not clobber old files at the same time.\n"));
|
||||
static RETSIGTYPE
|
||||
redirect_output_signal (int sig)
|
||||
{
|
||||
char tmp[100];
|
||||
signal (sig, redirect_output_signal);
|
||||
/* Please note that the double `%' in `%%s' is intentional, because
|
||||
redirect_output passes tmp through printf. */
|
||||
sprintf (tmp, _("%s received, redirecting output to `%%s'.\n"),
|
||||
(sig == SIGHUP ? "SIGHUP" :
|
||||
(sig == SIGUSR1 ? "SIGUSR1" :
|
||||
"WTF?!")));
|
||||
redirect_output (tmp);
|
||||
char *signal_name = (sig == SIGHUP ? "SIGHUP" :
|
||||
(sig == SIGUSR1 ? "SIGUSR1" :
|
||||
"WTF?!"));
|
||||
log_request_redirect_output (signal_name);
|
||||
progress_schedule_redirect ();
|
||||
signal (sig, redirect_output_signal);
|
||||
}
|
||||
#endif /* HAVE_SIGNAL */
|
||||
|
@ -36,7 +36,7 @@ extern int errno;
|
||||
#endif
|
||||
|
||||
/* Defined in log.c. */
|
||||
void redirect_output (const char *);
|
||||
void log_request_redirect_output PARAMS ((const char *));
|
||||
|
||||
static int windows_nt_p;
|
||||
|
||||
@ -103,10 +103,7 @@ ws_cleanup (void)
|
||||
static void
|
||||
ws_hangup (void)
|
||||
{
|
||||
redirect_output (_("\n\
|
||||
CTRL+Break received, redirecting output to `%s'.\n\
|
||||
Execution continued in background.\n\
|
||||
You may stop Wget by pressing CTRL+ALT+DELETE.\n"));
|
||||
log_request_redirect_output ("CTRL+Break");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -683,8 +683,10 @@ create_image (struct bar_progress *bp, long dltime)
|
||||
static void
|
||||
display_image (char *buf)
|
||||
{
|
||||
int old = log_set_save_context (0);
|
||||
logputs (LOG_VERBOSE, "\r");
|
||||
logputs (LOG_VERBOSE, buf);
|
||||
log_set_save_context (old);
|
||||
}
|
||||
|
||||
static void
|
||||
|
29
src/utils.c
29
src/utils.c
@ -84,21 +84,9 @@ extern int errno;
|
||||
static void
|
||||
memfatal (const char *what)
|
||||
{
|
||||
/* HACK: expose save_log_p from log.c, so we can turn it off in
|
||||
order to prevent saving the log. Saving the log is dangerous
|
||||
because logprintf() and logputs() can call malloc(), so this
|
||||
could infloop. When logging is turned off, infloop can no longer
|
||||
happen.
|
||||
|
||||
#### This is no longer really necessary because the new routines
|
||||
in log.c cons only if the line exceeds eighty characters. But
|
||||
this can come at the end of a line, so it's OK to be careful.
|
||||
|
||||
On a more serious note, it would be good to have a
|
||||
log_forced_shutdown() routine that exposes this cleanly. */
|
||||
extern int save_log_p;
|
||||
|
||||
save_log_p = 0;
|
||||
/* Make sure we don't try to store part of the log line, and thus
|
||||
call malloc. */
|
||||
log_set_save_context (0);
|
||||
logprintf (LOG_ALWAYS, _("%s: %s: Not enough memory.\n"), exec_name, what);
|
||||
exit (1);
|
||||
}
|
||||
@ -464,12 +452,17 @@ fork_to_background (void)
|
||||
else if (pid != 0)
|
||||
{
|
||||
/* parent, no error */
|
||||
printf (_("Continuing in background.\n"));
|
||||
printf (_("Continuing in background, pid %d.\n"), (int)pid);
|
||||
if (changedp)
|
||||
printf (_("Output will be written to `%s'.\n"), opt.lfilename);
|
||||
exit (0);
|
||||
exit (0); /* #### should we use _exit()? */
|
||||
}
|
||||
/* child: keep running */
|
||||
|
||||
/* child: give up the privileges and keep running. */
|
||||
setsid ();
|
||||
freopen ("/dev/null", "r", stdin);
|
||||
freopen ("/dev/null", "w", stdout);
|
||||
freopen ("/dev/null", "w", stderr);
|
||||
}
|
||||
#endif /* not WINDOWS */
|
||||
|
||||
|
@ -105,6 +105,7 @@ void debug_logprintf ();
|
||||
void logputs PARAMS ((enum log_options, const char *));
|
||||
void logflush PARAMS ((void));
|
||||
void log_set_flush PARAMS ((int));
|
||||
int log_set_save_context PARAMS ((int));
|
||||
|
||||
/* Defined in `utils.c', but used literally everywhere. */
|
||||
#ifndef DEBUG_MALLOC
|
||||
|
Loading…
Reference in New Issue
Block a user