Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

configurable abort on fatal errors #4943

Merged
merged 5 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backup/backupd.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ EXPORTED void fatal(const char* s, int code)
prot_flush(backupd_out);
}
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

Expand Down
3 changes: 3 additions & 0 deletions backup/ctl_backups.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ EXPORTED void fatal(const char *error, int code)
{
fprintf(stderr, "fatal error: %s\n", error);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 3 additions & 0 deletions backup/cyr_backup.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ EXPORTED void fatal(const char *error, int code)
{
fprintf(stderr, "fatal error: %s\n", error);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 3 additions & 0 deletions backup/restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ EXPORTED void fatal(const char *s, int code)
{
fprintf(stderr, "Fatal error: %s\n", s);
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
59 changes: 59 additions & 0 deletions cassandane/Cassandane/Cyrus/Simple.pm
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,63 @@ EOF
$self->assert_str_equals("test\r\n", $res->{1}{binary});
}

sub test_fatals_abort_enabled
:NoStartInstances
{
my ($self) = @_;

$self->{instance}->{config}->set(
'fatals_abort' => 'yes',
'prometheus_enabled' => 'no',
);
$self->_start_instances();

my $basedir = $self->{instance}->get_basedir();

# run `promstatsd -1` without having set up for prometheus, which should
# produce a "Prometheus metrics are not being tracked..." fatal error
eval {
$self->{instance}->run_command({ cyrus => 1 }, 'promstatsd', '-1');
};
my $e = $@;
$self->assert_not_null($e);
$self->assert_matches(qr{promstatsd pid \d+\) terminated by signal 6},
$e->{'-text'});

my @cores = $self->{instance}->find_cores();
if (@cores) {
# if we dumped core, there'd better only be one core file
$self->assert_num_equals(1, scalar @cores);

# don't barf on it existing during shutdown
unlink $cores[0];
}
}

sub test_fatals_abort_disabled
:NoStartInstances
{
my ($self) = @_;

$self->{instance}->{config}->set(
'fatals_abort' => 'no',
'prometheus_enabled' => 'no',
);
$self->_start_instances();

my $basedir = $self->{instance}->get_basedir();

# run `promstatsd -1` without having set up for prometheus, which should
# produce a "Prometheus metrics are not being tracked..." fatal error
eval {
$self->{instance}->run_command({ cyrus => 1 }, 'promstatsd', '-1');
};
my $e = $@;
$self->assert_not_null($e);
$self->assert_matches(qr{promstatsd pid \d+\) exited with code 78},
$e->{'-text'});

# post-test sanity checks will complain for us if a core was left behind
}

1;
18 changes: 18 additions & 0 deletions changes/next/fatals-abort
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
Description:

Adds an option for fatal errors to abort and produce a core dump.


Config changes:

fatals_abort


Upgrade instructions:

None


GitHub issue:

None
2 changes: 2 additions & 0 deletions imap/calalarmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ EXPORTED void fatal(const char *msg, int err)

cyrus_done();

if (err != EX_PROTOCOL && config_fatals_abort) abort();

exit(err);
}

Expand Down
4 changes: 4 additions & 0 deletions imap/cli_fatal.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

#include <stdlib.h>
#include <stdio.h>
#include <sysexits.h>

#include "global.h"
#include "xmalloc.h"
Expand All @@ -60,5 +61,8 @@ EXPORTED void fatal(const char *message, int code)
recurse_code = code;
fprintf(stderr, "fatal error: %s\n", message);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}
4 changes: 3 additions & 1 deletion imap/ctl_conversationsdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,8 @@ EXPORTED void fatal(const char* s, int code)
{
fprintf(stderr, "ctl_conversationsdb: %s\n", s);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

3 changes: 3 additions & 0 deletions imap/cvt_xlist_specialuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ EXPORTED void fatal(const char *s, int code)
{
fprintf(stderr, "Fatal error: %s\n", s);
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 3 additions & 0 deletions imap/deliver.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ EXPORTED void fatal(const char* s, int code)
prot_printf(deliver_out,"421 4.3.0 deliver: %s\r\n", s);
prot_flush(deliver_out);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 2 additions & 1 deletion imap/fud.c
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ EXPORTED void fatal(const char* s, int code)
recurse_code = code;
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

3 changes: 3 additions & 0 deletions imap/httpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,9 @@ EXPORTED void fatal(const char* s, int code)
}

syslog(LOG_ERR, "%s%s", fatal, s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

Expand Down
2 changes: 2 additions & 0 deletions imap/idled.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ EXPORTED void fatal(const char *msg, int err)

cyrus_done();

if (err != EX_PROTOCOL && config_fatals_abort) abort();

exit(err);
}

Expand Down
3 changes: 3 additions & 0 deletions imap/imapd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,9 @@ EXPORTED void fatal(const char *s, int code)
}

syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

Expand Down
4 changes: 2 additions & 2 deletions imap/lmtpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,10 +1034,10 @@ EXPORTED void fatal(const char* s, int code)

syslog(LOG_ERR, "FATAL: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

/* shouldn't return */
shut_down(code);

exit(code);
}

/*
Expand Down
3 changes: 3 additions & 0 deletions imap/message_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ EXPORTED void fatal(const char* s, int code)
{
fprintf(stderr, "message_test: %s\n", s);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
6 changes: 3 additions & 3 deletions imap/mupdate.c
Original file line number Diff line number Diff line change
Expand Up @@ -617,10 +617,10 @@ EXPORTED void fatal(const char *s, int code)
else recurse_code = code;

syslog(LOG_ERR, "%s", s);
shut_down(code);

/* NOTREACHED */
exit(code); /* shut up GCC */
if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

#define CHECKNEWLINE(c, ch) do { if ((ch) == '\r') (ch)=prot_getc((c)->pin); \
Expand Down
3 changes: 3 additions & 0 deletions imap/nntpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ EXPORTED void fatal(const char* s, int code)
}
if (stage) append_removestage(stage);
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

Expand Down
3 changes: 3 additions & 0 deletions imap/pop3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,9 @@ EXPORTED void fatal(const char* s, int code)
prot_flush(popd_out);
}
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}

Expand Down
2 changes: 2 additions & 0 deletions imap/promstatsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ EXPORTED void fatal(const char *msg, int err)
syslog(LOG_CRIT, "%s", msg);
syslog(LOG_NOTICE, "exiting");

if (err != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(err);
}

Expand Down
3 changes: 3 additions & 0 deletions imap/search_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ EXPORTED void fatal(const char* s, int code)
{
fprintf(stderr, "search_test: %s\n", s);
cyrus_done();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 2 additions & 1 deletion imap/smmapd.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ EXPORTED void fatal(const char* s, int code)
}
recurse_code = code;
syslog(LOG_ERR, "Fatal error: %s", s);
abort();

if (code != EX_PROTOCOL && config_fatals_abort) abort();

shut_down(code);
}
Expand Down
3 changes: 3 additions & 0 deletions imap/sync_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ EXPORTED void fatal(const char *s, int code)
{
fprintf(stderr, "Fatal error: %s\n", s);
syslog(LOG_ERR, "Fatal error: %s", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
3 changes: 3 additions & 0 deletions imap/sync_reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ static int usage(const char *name)
EXPORTED void fatal(const char* s, int code)
{
fprintf(stderr, "sync_reset: %s\n", s);

if (code != EX_PROTOCOL && config_fatals_abort) abort();

exit(code);
}

Expand Down
1 change: 1 addition & 0 deletions imap/sync_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ EXPORTED void fatal(const char* s, int code)
prot_flush(sync_out);
}
syslog(LOG_ERR, "Fatal error: %s", s);
if (code != EX_PROTOCOL && config_fatals_abort) abort();
shut_down(code);
}

Expand Down
3 changes: 3 additions & 0 deletions lib/assert.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,15 @@
#include "xmalloc.h"
#include "assert.h"

extern int config_fatals_abort;

EXPORTED void
assertionfailed(const char *file, int line, const char *expr)
{
char buf[1024];

snprintf(buf, sizeof(buf), "Internal error: assertion failed: %s: %d%s%s",
file, line, expr ? ": " : "", expr ? expr : "");
if (config_fatals_abort) abort();
fatal(buf, EX_SOFTWARE);
}
8 changes: 8 additions & 0 deletions lib/imapoptions
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,14 @@ Blank lines and lines beginning with ``#'' are ignored.
For backward compatibility, if no unit is specified, seconds is
assumed. */

{ "fatals_abort", 0, SWITCH, "UNRELEASED" }
/* If enabled, when fatal errors are detected, Cyrus will call abort()
to produce a core dump, unless the error was due to a misbehaving
client. This is useful if you have the ability to debug a core dump.
.PP
If not enabled (the default), the process will exit normally with
an error code. */

{ "flushseenstate", 1, SWITCH, "2.5.0", "2.5.0" }
/* Deprecated. No longer used. */

Expand Down
5 changes: 5 additions & 0 deletions lib/libconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ EXPORTED int config_qosmarking;
EXPORTED int config_debug;
EXPORTED toggle_debug_cb config_toggle_debug_cb = NULL;
EXPORTED int config_debug_slowio = 0;
EXPORTED int config_fatals_abort = 0;

static int config_loaded;

Expand Down Expand Up @@ -663,6 +664,7 @@ EXPORTED void config_reset(void)
config_debug = 0;
config_toggle_debug_cb = NULL;
config_debug_slowio = 0;
config_fatals_abort = 0;

/* reset all the options */
for (opt = IMAPOPT_ZERO; opt < IMAPOPT_LAST; opt++) {
Expand Down Expand Up @@ -893,6 +895,9 @@ EXPORTED void config_read(const char *alt_config, const int config_need_data)

/* do we want artificially-slow I/O ops */
config_debug_slowio = config_getswitch(IMAPOPT_DEBUG_SLOWIO);

/* do we want to abort() on fatal errors */
config_fatals_abort = config_getswitch(IMAPOPT_FATALS_ABORT);
}

#define GROWSIZE 4096
Expand Down
1 change: 1 addition & 0 deletions lib/libconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ extern unsigned config_maxword;
extern int config_qosmarking;
extern int config_debug;
extern int config_debug_slowio;
extern int config_fatals_abort;

/* for toggling config_debug and its behaviours at runtime */
typedef void (*toggle_debug_cb)(void);
Expand Down
Loading