abort() has the sometimes undesirable side-effect of generating a core dump. If that is not needed, SIGKILL has the same effect of abruptly crash qemu; without a core dump.
Therefore, this patch allows to use the qemu-io abort command to raise any signal. Signed-off-by: Max Reitz <mre...@redhat.com> --- qemu-io-cmds.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/qemu-io-cmds.c b/qemu-io-cmds.c index d94fb1e..5d39cf4 100644 --- a/qemu-io-cmds.c +++ b/qemu-io-cmds.c @@ -2036,18 +2036,71 @@ static const cmdinfo_t wait_break_cmd = { .oneline = "waits for the suspension of a request", }; -static int abort_f(BlockDriverState *bs, int argc, char **argv) + +static void abort_help(void) { - abort(); + printf( +"\n" +" simulates a program crash\n" +"\n" +" Invokes abort(), or raise(signal) if a signal number is specified.\n" +" -S, -- number of the signal to raise()\n" +"\n"); } +static int abort_f(BlockDriverState *bs, int argc, char **argv); + static const cmdinfo_t abort_cmd = { .name = "abort", .cfunc = abort_f, + .argmin = 0, + .argmax = 2, .flags = CMD_NOFILE_OK, - .oneline = "simulate a program crash using abort(3)", + .args = "[-S signal]", + .oneline = "simulate a program crash", + .help = abort_help, }; +static int abort_f(BlockDriverState *bs, int argc, char **argv) +{ + int c; + int sig = -1; + + while ((c = getopt(argc, argv, "S:")) != EOF) { + switch (c) { + case 'S': + sig = cvtnum(optarg); + if (sig < 0) { + printf("non-numeric signal number argument -- %s\n", optarg); + return 0; + } + break; + + default: + return qemuio_command_usage(&abort_cmd); + } + } + + if (optind != argc) { + return qemuio_command_usage(&abort_cmd); + } + + if (sig < 0) { + abort(); + } else { + /* While abort() does flush all open streams, using raise() to kill this + * process does not necessarily. At least stdout and stderr (although + * the latter should be non-buffered anyway) should be flushed, though. + */ + fflush(stdout); + fflush(stderr); + + raise(sig); + /* raise() may return */ + return 0; + } +} + static void sleep_cb(void *opaque) { bool *expired = opaque; -- 1.9.3