Skip to content

Commit

Permalink
Merge pull request #4943 from elliefm/v311/fatals-abort
Browse files Browse the repository at this point in the history
configurable abort on fatal errors
  • Loading branch information
elliefm committed Aug 19, 2024
2 parents 96f5868 + ed5d2b9 commit 352f9a0
Show file tree
Hide file tree
Showing 39 changed files with 195 additions and 12 deletions.
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 @@ -1442,6 +1442,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 @@ -111,6 +111,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

0 comments on commit 352f9a0

Please sign in to comment.