Allow corewatcher to try multiple submit urls
authorWilliam Douglas <william.douglas@linux.intel.com>
Thu, 3 Mar 2011 17:43:59 +0000 (09:43 -0800)
committerWilliam Douglas <william.douglas@linux.intel.com>
Thu, 3 Mar 2011 17:43:59 +0000 (09:43 -0800)
Bugfixes:
- Fixed issue with set_wrapped_app not getting correct executable.
- Various memory leaks plugged.

Enhancements:
- Read multiple urls from config, try until one works.
- Write url submitted to syslog
- Write coredump text to file

configfile.c
coredump.c
corewatcher.c
corewatcher.h
find_file.c
submit.c

index 840c423..58c970f 100644 (file)
@@ -36,7 +36,8 @@
  */
 int opted_in;
 int allow_distro_to_pass_on;
-char *submit_url;
+char *submit_url[MAX_URLS];
+int url_count = 0;
 extern int do_unlink;
 
 void read_config_file(char *filename)
@@ -85,15 +86,15 @@ void read_config_file(char *filename)
                                do_unlink = 1;
                }
                c = strstr(line, "submit-url ");
-               if (c) {
+               if (c && url_count <= MAX_URLS) {
                        c += 11;
                        c = strstr(c, "http:");
                        if (c)
-                               submit_url = strdup(c);
+                               submit_url[url_count++] = strdup(c);
                }
                free(line);
        }
        fclose(file);
-       if (!submit_url)
-               submit_url = strdup("http://crashdb.meego.com/submitbug.php");
+       if (!url_count)
+               submit_url[url_count++] = strdup("http://crashdb.meego.com/submitbug.php");
 }
index ad166ca..c76e4e0 100644 (file)
@@ -28,6 +28,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include <fcntl.h>
 
 #include <asm/unistd.h>
 #include <sys/types.h>
@@ -41,7 +42,6 @@
 int do_unlink = 0;
 int uid;
 int sig;
-char *corefile;
 char *package;
 char *component;
 char *arch;
@@ -82,7 +82,7 @@ static char *get_release(void) {
        return line;
 }
 
-void set_wrapped_app(char *line)
+char *set_wrapped_app(char *line)
 {
        char *dline = NULL, *app = NULL, delim[] = " '";
 
@@ -97,15 +97,12 @@ void set_wrapped_app(char *line)
                app = strtok(NULL, delim);
        }
 
-       if (app != NULL)
-               /*
-                * This may return NULL if app isn't on the path
-                * but we aren't going to worry about that here.
-                */
-               app = find_executable(app);
        free(dline);
-
-       return;
+       /*
+        * This may return NULL if app isn't on the path
+        * but we aren't going to worry about that here.
+        */
+       return find_executable(app);
 }
 
 void get_package_info(char *appfile) {
@@ -116,44 +113,55 @@ void get_package_info(char *appfile) {
        size_t size = 0;
 
        if (asprintf(&command, "rpm -q --whatprovides %s --queryformat \"%%{NAME}-%%{VERSION}-%%{RELEASE}-%%{ARCH}\"", appfile) < 0) {
-               line = strdup("Unknown");
+               package = strdup("Unknown");
        } else {
                file = popen(command, "r");
-
                ret = getline(&line, &size, file);
-               if ((!size) || (ret < 0))
+               if ((!size) || (ret < 0)) {
+                       free(line);
                        line = strdup("Unknown");
+               }
                c = strchr(line, '\n');
                if (c) *c = 0;
                pclose(file);
+               package = strdup(line);
        }
-       package = strdup(line);
+       free(line);
+       free(command);
 
        if (asprintf(&command, "rpm -q --whatprovides %s --queryformat \"%%{NAME}\"", appfile) < 0) {
-               line = strdup("Unknown");
+               component = strdup("Unknown");
        } else {
                file = popen(command, "r");
                ret = getline(&line, &size, file);
-               if ((!size) || (ret < 0))
+               if ((!size) || (ret < 0)) {
+                       free(line);
                        line = strdup("Unknown");
+               }
                c = strchr(line, '\n');
                if (c) *c = 0;
                pclose(file);
+               component = strdup(line);
        }
-       component = strdup(line);
+       free(line);
+       free(command);
 
        if (asprintf(&command, "rpm -q --whatprovides %s --queryformat \"%%{ARCH}\"", appfile) < 0) {
-               line = strdup("Unknown");
+               arch = strdup("Unknown");
        } else {
                file = popen(command, "r");
                ret = getline(&line, &size, file);
-               if ((!size) || (ret < 0))
+               if ((!size) || (ret < 0)) {
+                       free(line);
                        line = strdup("Unknown");
+               }
                c = strchr(line, '\n');
                if (c) *c = 0;
                pclose(file);
+               arch = strdup(line);
        }
-       arch = strdup(line);
+       free(line);
+       free(command);
 }
 
 char *signame(int sig)
@@ -179,10 +187,12 @@ static char *get_kernel(void) {
 
        if (asprintf(&command, "uname -r") < 0) {
                line = strdup("Unknown");
+               free(command);
                return line;
        }
 
        file = popen(command, "r");
+       free(command);
 
        ret = getline(&line, &size, file);
        if ((!size) || (ret < 0)) {
@@ -234,6 +244,8 @@ char *build_core_header(char *appfile, char *corefile) {
        free(kernel);
        free(package);
        free(release);
+       free(component);
+       free(arch);
 
        if (ret < 0)
                result = strdup("Unknown");
@@ -249,14 +261,20 @@ char *extract_core(char *corefile)
        FILE *file;
 
        coredump = find_coredump(corefile);
-       if (!coredump)
+       if (!coredump) {
+               free(coredump);
                return NULL;
+       }
        appfile = find_executable(coredump);
+       /* coredump no longer used, so free it as it was strdup'd */
+       free(coredump);
        if (!appfile)
                return NULL;
 
-       if (asprintf(&command, "LANG=C gdb --batch -f %s %s -x /var/lib/corewatcher/gdb.command 2> /dev/null", appfile, corefile) < 0)
+       if (asprintf(&command, "LANG=C gdb --batch -f %s %s -x /var/lib/corewatcher/gdb.command 2> /dev/null", appfile, corefile) < 0) {
+               free(command);
                return NULL;
+       }
 
        /*
         * Scan core dump in case meego-tablet-wrapper was used
@@ -274,12 +292,15 @@ char *extract_core(char *corefile)
                if (ret < 0)
                        break;
 
-               if (strstr(line, "Core was generated by `")) {
+               if (strstr(line, "Core was generated by") &&
+                   strstr(line, "--app")) {
                        /* attempt to update appfile */
-                       set_wrapped_app(line);
+                       appfile = set_wrapped_app(line);
                        break;
                }
        }
+       free(line);
+       pclose(file);
 
        c1 = build_core_header(appfile, corefile);
 
@@ -289,7 +310,6 @@ char *extract_core(char *corefile)
                int ret;
 
                c2 = c1;
-               line = NULL;
                ret = getline(&line, &size, file);
                if (!size)
                        break;
@@ -297,11 +317,9 @@ char *extract_core(char *corefile)
                        break;
 
                if (strstr(line, "no debugging symbols found")) {
-                       free(line);
                        continue;
                }
                if (strstr(line, "reason: ")) {
-                       free(line);
                        continue;
                }
 
@@ -311,17 +329,35 @@ char *extract_core(char *corefile)
                                continue;
                        free(c2);
                } else {
+                       free(c1);
                        c1 = NULL;
                        if (asprintf(&c1, "%s", line) < 0)
                                continue;
                }
-               free(line);
        }
+       free(line);
        pclose(file);
        free(command);
        return c1;
 }
 
+void write_core_detail_file(char *filename, char *text)
+{
+       int fd;
+       char *pid;
+       char detail_filename[8192];
+
+       if (!(pid = strstr(filename, ".")))
+               return;
+
+       snprintf(detail_filename, 8192, "/tmp/%s.txt", ++pid);
+       if ((fd = open(detail_filename, O_WRONLY | O_CREAT | O_TRUNC, 0)) != -1) {
+               write(fd, text, strlen(text));
+               fchmod(fd, 0644);
+               close(fd);
+       }
+}
+
 void process_corefile(char *filename)
 {
        char *ptr;
@@ -330,11 +366,16 @@ void process_corefile(char *filename)
 
        if (!ptr) {
                unlink(filename);
+               free(ptr);
                return;
        }
 
        queue_backtrace(ptr);
        fprintf(stderr, "---[start of coredump]---\n%s\n---[end of coredump]---\n", ptr);
+
+       /* try to write coredump text details to text file */
+       write_core_detail_file(filename, ptr);
+
        sprintf(newfile,"%s.processed", filename);
        if (do_unlink)
                unlink(filename);
@@ -375,5 +416,6 @@ int scan_dmesg(void __unused *unused)
                submit_queue();
        else if (opted_in >= 1)
                ask_permission();
+       closedir(dir);
        return 1;
 }
index 7b72fe6..9549527 100644 (file)
@@ -173,6 +173,7 @@ int main(int argc, char**argv)
        DBusError error;
        int godaemon = 1;
        int debug = 0;
+       int j = 0;
 
 /*
  * Signal the kernel that we're not timing critical
@@ -264,7 +265,8 @@ int main(int argc, char**argv)
                g_main_loop_unref(loop);
                dbus_bus_remove_match(bus, "type='signal',interface='org.corewatcher.submit.ping'", &error);
                dbus_bus_remove_match(bus, "type='signal',interface='org.corewatcher.submit.permission'", &error);
-               free(submit_url);
+               for (j = 0; j < url_count; j++)
+                       free(submit_url[j]);
                fprintf(stderr, "+ Exiting from testmode\n");
                return EXIT_SUCCESS;
        }
@@ -278,7 +280,8 @@ int main(int argc, char**argv)
        dbus_bus_remove_match(bus, "type='signal',interface='org.corewatcher.submit.permission'", &error);
 
        g_main_loop_unref(loop);
-       free(submit_url);
+       for (j = 0; j < url_count; j++)
+               free(submit_url[j]);
 
        return EXIT_SUCCESS;
 }
index 2a3ebc6..7b68bea 100644 (file)
@@ -30,6 +30,8 @@
 #define barrier() __asm__ __volatile__("": : :"memory")
 #define __unused  __attribute__ ((__unused__))
 
+#define MAX_URLS 9
+
 extern void queue_backtrace(char *oops);
 extern void submit_queue(void);
 extern void clear_queue(void);
@@ -43,7 +45,8 @@ extern void dbus_say_thanks(char *url);
 
 extern int opted_in;
 extern int allow_distro_to_pass_on;
-extern char *submit_url;
+extern char *submit_url[MAX_URLS];
+extern int url_count;
 
 extern int testmode;
 extern int pinged;
index 6d9de80..6c0e1f8 100644 (file)
@@ -33,9 +33,7 @@ char *find_executable(char *fragment)
 
        fprintf(stderr, "+ Looking for %s\n", fragment);
 
-       path = strdup(getenv("PATH"));
-
-       if (strlen(fragment) < 3)
+       if (fragment == NULL || strlen(fragment) < 3)
                return NULL;
 
        /* Deal with absolute paths first */
@@ -44,6 +42,8 @@ char *find_executable(char *fragment)
                return filename;
        }
 
+       path = strdup(getenv("PATH"));
+
        c1 = path;
        while (c1 && strlen(c1)>0) {
                c2 = strchr(c1, ':');
@@ -52,11 +52,13 @@ char *find_executable(char *fragment)
                if (!access(path_filename, X_OK)) {
                        printf("Found %s\n", path_filename);
                        strcpy(filename, path_filename);
+                       free(path);
                        return filename;
                }
                c1 = c2;
                if (c2) c1++;
        }
+       free(path);
        return NULL;
 }
 
index 1ede618..d3f0e52 100644 (file)
--- a/submit.c
+++ b/submit.c
@@ -178,10 +178,10 @@ static void print_queue(void)
 
 }
 
-static void write_logfile(int count)
+static void write_logfile(int count, char *wsubmit_url)
 {
        openlog("corewatcher", 0, LOG_KERN);
-       syslog(LOG_WARNING, "Submitted %i coredump signatures to %s", count, submit_url);
+       syslog(LOG_WARNING, "Submitted %i coredump signatures to %s", count, wsubmit_url);
        closelog();
 }
 
@@ -201,10 +201,11 @@ size_t writefunction( void *ptr, size_t size, size_t nmemb, void __attribute((un
                if (c2) *c2 = 0;
                strncpy(result_url, c1, 4095);
        }
+       free(c);
        return size * nmemb;
 }
 
-void submit_queue(void)
+void submit_queue_with_url(char *wsubmit_url)
 {
        int result;
        struct oops *oops;
@@ -212,15 +213,8 @@ void submit_queue(void)
        CURL *handle;
        int count = 0;
 
-       memset(result_url, 0, 4096);
-
-       if (testmode) {
-               print_queue();
-               return;
-       }
-
        handle = curl_easy_init();
-       curl_easy_setopt(handle, CURLOPT_URL, submit_url);
+       curl_easy_setopt(handle, CURLOPT_URL, wsubmit_url);
 
        queue = queued_backtraces;
        queued_backtraces = NULL;
@@ -258,7 +252,7 @@ void submit_queue(void)
        curl_easy_cleanup(handle);
 
        if (count && !testmode)
-               write_logfile(count);
+               write_logfile(count, wsubmit_url);
 
        if (count)
                dbus_say_thanks(result_url);
@@ -272,6 +266,33 @@ void submit_queue(void)
        }
 }
 
+void submit_queue(void)
+{
+       int i;
+       CURL *handle;
+
+       memset(result_url, 0, 4096);
+
+       if (testmode) {
+               print_queue();
+               return;
+       }
+
+       handle = curl_easy_init();
+       curl_easy_setopt(handle, CURLOPT_NOBODY, 1);
+       curl_easy_setopt(handle, CURLOPT_TIMEOUT, 5);
+
+       for (i = 0; i < url_count; i++) {
+               curl_easy_setopt(handle, CURLOPT_URL, submit_url[i]);
+               if (!curl_easy_perform(handle)) {
+                       submit_queue_with_url(submit_url[i]);
+                       break;
+               }
+       }
+
+       curl_easy_cleanup(handle);
+}
+
 void clear_queue(void)
 {
        struct oops *oops, *next;
@@ -287,7 +308,7 @@ void clear_queue(void)
                free(oops);
                oops = next;
        }
-       write_logfile(0);
+       write_logfile(0, "Unknown");
 }
 
 void ask_permission(void)