Changeset 5612

Add "core dump|analyse" commands to aid in debugging (maybe)

Use gdb to attempt core dumps without halting callweaver and to generate
an on-the-fly core analysis (using safe_callweaver) that is mailed to
one or more addresses.

Committed by:  mjagdis
Date:  Feb 05 2010 * 00:41 (6 months ago)

Affected files:

callweaver/trunk/corelib/Makefile.am (unified diff)

r5594r5612
8989
9090 CORE_NODIST = defaults.h
9191
92 CORE_CFLAGS = $(AM_CFLAGS) -D_REENTRANT -DCW_API_IMPLEMENTATION
92 CORE_CFLAGS = $(AM_CFLAGS) -D_REENTRANT -DCW_API_IMPLEMENTATION -DCW_UTILSDIR="$(cwutilsdir)"
9393 if !WANT_DEBUG
9494 CORE_CFLAGS += -fomit-frame-pointer
9595 #CORE_CFLAGS += -DCW_MUTEX_INIT_W_CONSTRUCTORS

callweaver/trunk/corelib/callweaver.c (unified diff)

r5610r5612
788788 " If a timeout is given and CallWeaver is unable to stop in this\n"
789789 " any seconds an immediate stop will be initiated.\n";
790790
791 static const char core_analyse_help[] =
792 "Usage: core analyse emailadress [...]\n"
793 " Causes CallWeaver to generate a core analysis and email it to the specified\n"
794 " addresses. Success is dependent on having working \"gdb\" and \"mail\" applications\n"
795 " installed.\n"
796 "\n"
797 " Note that this command WILL cause an interruption in service as gdb will suspend\n"
798 " the process while it works. This is hopefully kept to a minimum.\n";
799
800 static const char core_dump_and_halt_help[] =
801 "Usage: core dump and halt\n"
802 " Causes CallWeaver to dump core and halt immediately. All active calls will be\n"
803 " terminated. CallWeaver will NOT restart itself but may be restarted automatically\n"
804 " if you are using some form of external process monitor.\n";
805
806 static const char core_dump_and_continue_help[] =
807 "Usage: core dump and continue\n"
808 " Causes CallWeaver to dump core and continue operation.\n"
809 " Success is dependent on gdb being installed and accessible via $PATH. Even if gdb\n"
810 " is not available \"core dump and halt\" will still work (but obviously causes\n"
811 " CallWeaver to halt in the process).\n";
812
791813 static const char bang_help[] =
792814 "Usage: !<command>\n"
793815 " Executes a given shell command\n";
------
906928 return RESULT_SUCCESS;
907929 }
908930
931 static int core_dump(struct cw_dynstr **ds_p, int argc, char *argv[])
932 {
933 struct cw_dynstr *buf = NULL;
934 int res;
935
936 CW_UNUSED(ds_p);
937
938 if (argc != 4)
939 return RESULT_SHOWUSAGE;
940
941 res = RESULT_FAILURE;
942
943 if (!strcmp(argv[3], "halt")) {
944 *(int *)0 = 1;
945 } else {
946 cw_dynstr_printf(&buf, "gdb $( type -p \"%s\" ) %u <<EOF\n"
947 "generate-core-file\n"
948 "quit\n"
949 "EOF\n",
950 _argv[0], cw_mainpid);
951
952 if (buf && !buf->error) {
953 cw_safe_system(buf->data);
954 res = RESULT_SUCCESS;
955 } else
956 cw_log(CW_LOG_ERROR, "Out of memory!\n");
957 }
958
959 return res;
960
961 }
962
963 static int core_analyse(struct cw_dynstr **ds_p, int argc, char *argv[])
964 {
965 char buf[1024];
966 struct cw_dynstr *cmd = NULL;
967 FILE *fd;
968 int i;
969
970 cw_dynstr_printf(&cmd, "CALLWEAVER_NOTIFYDEV='");
971
972 for (i = 2; i < argc; i++) {
973 const char *p = argv[i];
974
975 cw_dynstr_printf(&cmd, "%s ", (i != 2 ? "," : ""));
976
977 while (*p) {
978 int n = strcspn(p, "'");
979 cw_dynstr_printf(&cmd, "%.*s", n, p);
980 if (!p[n])
981 break;
982 cw_dynstr_printf(&cmd, "\\%c", p[n]);
983 p += n + 1;
984 }
985 }
986
987 cw_dynstr_printf(&cmd, "' '%s/cw_coreanalyse' '%s' %u 'Live core analysis' 2>&1",
988 CW_CPP_DO(CW_CPP_MKSTR, CW_UTILSDIR), _argv[0], (unsigned int)cw_mainpid);
989
990 i = RESULT_FAILURE;
991
992 if (cmd) {
993 if (!cmd->error) {
994 if ((fd = popen(cmd->data, "r"))) {
995 while ((i = fread(buf, 1, sizeof(buf), fd)) > 0)
996 if (cw_dynstr_printf(ds_p, "%.*s", i, buf))
997 pclose(fd);
998 } else
999 cw_dynstr_printf(ds_p, "popen: %s\n", strerror(errno));
1000
1001 i = RESULT_SUCCESS;
1002 }
1003
1004 cw_dynstr_free(cmd);
1005 }
1006
1007 if (i != RESULT_SUCCESS)
1008 cw_log(CW_LOG_ERROR, "Out of memory!\n");
1009
1010 return i;
1011 }
1012
1013
9091014 static int handle_bang(struct cw_dynstr **ds_p, int argc, char *argv[])
9101015 {
9111016 CW_UNUSED(ds_p);
------
9531058 .usage = shutdown_gracefully_help,
9541059 },
9551060 {
956 .cmda = { "stop", "when","convenient", NULL },
1061 .cmda = { "stop", "when", "convenient", NULL },
9571062 .handler = handle_shutdown_when_convenient,
9581063 .summary = "Shut down CallWeaver when there are no calls in progress",
9591064 .usage = shutdown_when_convenient_help,
------
9771082 .usage = restart_when_convenient_help,
9781083 },
9791084 {
1085 .cmda = { "core", "analyse", NULL },
1086 .handler = core_analyse,
1087 .summary = "Generate a core analysis.",
1088 .usage = core_analyse_help,
1089 },
1090 {
1091 .cmda = { "core", "dump", "and", "halt", NULL },
1092 .handler = core_dump,
1093 .summary = "Dump core and halt.",
1094 .usage = core_dump_and_halt_help,
1095 },
1096 {
1097 .cmda = { "core", "dump", "and", "continue", NULL },
1098 .handler = core_dump,
1099 .summary = "Dump core and continue.",
1100 .usage = core_dump_and_continue_help,
1101 },
1102 {
9801103 .cmda = { "!", NULL },
9811104 .handler = handle_bang,
9821105 .summary = "Execute a shell command",

callweaver/trunk/include/callweaver/preprocessor.h (unified diff)

r5560r5612
4040 #ifndef _CALLWEAVER_PREPROCESSOR_H
4141 #define _CALLWEAVER_PREPROCESSOR_H
4242
43 #define CW_CPP_MKSTR(a) # a
44
4345 #define CW_CPP_CAT(a, b) a ## b
4446 #define CW_CPP_DEBRACKET(...) __VA_ARGS__
4547 #define CW_CPP_DO(op, ...) op(__VA_ARGS__)