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 (diff)
callweaver/trunk/corelib/callweaver.c (diff)
callweaver/trunk/include/callweaver/preprocessor.h (diff)
callweaver/trunk/corelib/Makefile.am (unified diff)
| r5594 | r5612 | |
|---|---|---|
| 89 | 89 | |
| 90 | 90 | CORE_NODIST = defaults.h |
| 91 | 91 | |
| 92 | CORE_CFLAGS = $(AM_CFLAGS) -D_REENTRANT -DCW_API_IMPLEMENTATION | |
| 92 | CORE_CFLAGS = $(AM_CFLAGS) -D_REENTRANT -DCW_API_IMPLEMENTATION -DCW_UTILSDIR="$(cwutilsdir)" | |
| 93 | 93 | if !WANT_DEBUG |
| 94 | 94 | CORE_CFLAGS += -fomit-frame-pointer |
| 95 | 95 | #CORE_CFLAGS += -DCW_MUTEX_INIT_W_CONSTRUCTORS |
callweaver/trunk/corelib/callweaver.c (unified diff)
| r5610 | r5612 | |
|---|---|---|
| 788 | 788 | " If a timeout is given and CallWeaver is unable to stop in this\n" |
| 789 | 789 | " any seconds an immediate stop will be initiated.\n"; |
| 790 | 790 | |
| 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 | ||
| 791 | 813 | static const char bang_help[] = |
| 792 | 814 | "Usage: !<command>\n" |
| 793 | 815 | " Executes a given shell command\n"; |
| --- | --- | |
| 906 | 928 | return RESULT_SUCCESS; |
| 907 | 929 | } |
| 908 | 930 | |
| 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 | ||
| 909 | 1014 | static int handle_bang(struct cw_dynstr **ds_p, int argc, char *argv[]) |
| 910 | 1015 | { |
| 911 | 1016 | CW_UNUSED(ds_p); |
| --- | --- | |
| 953 | 1058 | .usage = shutdown_gracefully_help, |
| 954 | 1059 | }, |
| 955 | 1060 | { |
| 956 | .cmda = { "stop", "when","convenient", NULL }, | |
| 1061 | .cmda = { "stop", "when", "convenient", NULL }, | |
| 957 | 1062 | .handler = handle_shutdown_when_convenient, |
| 958 | 1063 | .summary = "Shut down CallWeaver when there are no calls in progress", |
| 959 | 1064 | .usage = shutdown_when_convenient_help, |
| --- | --- | |
| 977 | 1082 | .usage = restart_when_convenient_help, |
| 978 | 1083 | }, |
| 979 | 1084 | { |
| 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 | { | |
| 980 | 1103 | .cmda = { "!", NULL }, |
| 981 | 1104 | .handler = handle_bang, |
| 982 | 1105 | .summary = "Execute a shell command", |
callweaver/trunk/include/callweaver/preprocessor.h (unified diff)
| r5560 | r5612 | |
|---|---|---|
| 40 | 40 | #ifndef _CALLWEAVER_PREPROCESSOR_H |
| 41 | 41 | #define _CALLWEAVER_PREPROCESSOR_H |
| 42 | 42 | |
| 43 | #define CW_CPP_MKSTR(a) # a | |
| 44 | ||
| 43 | 45 | #define CW_CPP_CAT(a, b) a ## b |
| 44 | 46 | #define CW_CPP_DEBRACKET(...) __VA_ARGS__ |
| 45 | 47 | #define CW_CPP_DO(op, ...) op(__VA_ARGS__) |
![Home changeset 5612 [home]](/images/logo.png?1180520111)
RSS Feeds