Reduce heap usage 69/215469/8
authorMateusz Moscicki <m.moscicki2@partner.samsung.com>
Tue, 8 Oct 2019 10:13:14 +0000 (12:13 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Thu, 10 Oct 2019 12:51:46 +0000 (14:51 +0200)
When *.so_info was writing, for TPK packages, a complete list of
packages and paths was built, to find a RPM package that contains the
file. Now only the list of files is kept in memory, and then RPM
database is iterated to find suitable package.

Change-Id: I779661de26afd959945d441ba5ad160c99a014b2

src/crash-manager/so-info.c

index bc1720b..b449791 100644 (file)
 
 #define BID_SNAME ".note.gnu.build-id"
 
+struct rpm_info {
+       char *file_path;
+       char *app_name;
+       char *build_id;
+       char *rpm_info;
+};
+
+void rpm_info_free(struct rpm_info* ri)
+{
+       free(ri->file_path);
+       free(ri->app_name);
+       free(ri->build_id);
+       free(ri->rpm_info);
+       free(ri);
+}
 
 static unsigned char *map_file(const char *filename, int64_t *size)
 {
@@ -237,26 +252,26 @@ void free_rpm(rpmts ts)
        }
 }
 
-char* get_rpm_info_as_string(Header h)
+char* get_rpm_info_as_string_for_pkgname(Header h, const char *pkg_name)
 {
-       const char *name, *version, *release, *arch;
+       char *result = NULL;
 
-       name = headerGetString(h, RPMTAG_NAME);
-       version = headerGetString(h, RPMTAG_VERSION);
-       release = headerGetString(h, RPMTAG_RELEASE);
-       arch = headerGetString(h, RPMTAG_ARCH);
+       const char *version = headerGetString(h, RPMTAG_VERSION);
+       const char *release = headerGetString(h, RPMTAG_RELEASE);
+       const char *arch    = headerGetString(h, RPMTAG_ARCH);
 
-       int info_len = strlen(name) + strlen(version) +
-                                  strlen(release) + strlen(arch) + 3;
+       if (version == NULL || release == NULL || arch == NULL)
+               _E("Failed to get version, release and arch for: %s", pkg_name);
+       else if (asprintf(&result, "%s;%s;%s;%s", pkg_name, version, release, arch) == -1)
+               _E("asprintf() error: %m");
 
-       char *res = (char *)malloc(info_len + 1);
-       if (res == NULL) {
-               _E("Failed to allocate memory: %m");
-               return NULL;
-       }
-       snprintf(res, info_len + 1, "%s;%s;%s;%s", name, version, release, arch);
+       return result;
+}
 
-       return res;
+char* get_rpm_info_as_string(Header h)
+{
+       const char *name = headerGetString(h, RPMTAG_NAME);
+       return get_rpm_info_as_string_for_pkgname(h, name);
 }
 
 char* get_rpm_info(rpmts ts, const char* filename)
@@ -284,28 +299,23 @@ char* get_rpm_info(rpmts ts, const char* filename)
        return rpm_info;
 }
 
-struct rpm_file {
-       char *pkg_name;
-       char *file_name;
-};
-
-GSList* create_tpk_list(rpmts ts)
+void search_for_tpk(rpmts ts, GSList *pkgs)
 {
-       GSList *tpk_list = NULL;
-
        rpmdbMatchIterator mi = rpmtsInitIterator(ts, RPMTAG_NAME, NULL, 0);
        if (mi == NULL) {
                _E("Failed to init rpmdb match iterator");
-               goto end;
+               return;
        }
 
-       for (Header h = rpmdbNextIterator(mi); h; h = rpmdbNextIterator(mi)) {
+       guint count = g_slist_length(pkgs); // Initial number of packets with empty rpm_info
+
+       for (Header h = rpmdbNextIterator(mi); count > 0 && h; h = rpmdbNextIterator(mi)) {
                const char *pkg_name = headerGetString(h, RPMTAG_NAME);
                if (pkg_name == NULL)
                        continue;
                rpmfi fi = rpmfiNew(NULL, h, RPMTAG_FILENAMES, 0);
 
-               while (rpmfiNext(fi) != -1) {
+               while (count > 0 && rpmfiNext(fi) != -1) {
                        const char *file_name = rpmfiFN(fi);
                        size_t file_name_len = strlen(file_name);
 
@@ -313,41 +323,28 @@ GSList* create_tpk_list(rpmts ts)
                            strcmp(&file_name[file_name_len-4], ".tpk") != 0)
                                continue;
 
-                       const char *version = headerGetString(h, RPMTAG_VERSION);
-                       const char *release = headerGetString(h, RPMTAG_RELEASE);
-                       const char *arch = headerGetString(h, RPMTAG_ARCH);
+                       for (GSList *iterator = pkgs; iterator; iterator = iterator->next) {
+                               struct rpm_info *ri = (struct rpm_info *)iterator->data;
+                               if (ri->rpm_info != NULL)
+                                       continue;
 
-                       if (version == NULL || release == NULL || arch == NULL)
-                               continue;
+                               if (strstr(file_name, ri->app_name) == NULL)
+                                       continue;
 
-                       struct rpm_file *rpm = (struct rpm_file*)malloc(sizeof(*rpm));
-                       if (rpm == NULL) {
-                               _E("malloc() error (%m). Report (*.so_info) may be incomplete.");
-                               continue;
-                       }
+                               char *info = get_rpm_info_as_string_for_pkgname(h, pkg_name);
+                               if (info == NULL)
+                                       continue;
 
-                       if (asprintf(&rpm->pkg_name, "%s;%s;%s;%s",
-                                       pkg_name, version, release, arch) == -1) {
-                               _E("asprintf() error: %m");
-                               free(rpm);
-                               continue;
-                       }
-                       rpm->file_name = strdup(file_name);
-                       if (rpm->file_name == NULL) {
-                               _E("strdup() error: %m");
-                               free(rpm->pkg_name);
-                               free(rpm);
-                               continue;
+                               ri->rpm_info = info;
+                               count--;
+                               break;
                        }
-                       tpk_list = g_slist_append(tpk_list, rpm);
                }
+
+               rpmfiFree(fi);
        }
-       rpmdbFreeIterator(mi);
 
-       if (tpk_list == NULL)
-               _E("No RPM packages containing *.tpk files found");
-end:
-       return tpk_list;
+       rpmdbFreeIterator(mi);
 }
 
 char* get_app_name_from_path(const char *file_path)
@@ -368,85 +365,82 @@ char* get_app_name_from_path(const char *file_path)
        return NULL;
 }
 
-char* get_rpm_info_for_tpk(GSList *tpk_list, const char *file_path)
+void get_and_save_so_info(char *map_path, char *out_path)
 {
-       char *app_name = get_app_name_from_path(file_path);
-       if (app_name == NULL)
-               return NULL;
-
-       char *res = NULL;
-
-       for (GSList *iterator = tpk_list; iterator; iterator = iterator->next) {
-               struct rpm_file *rpm_pkg = (struct rpm_file *)iterator->data;
-
-               if (strstr(rpm_pkg->file_name, app_name) != NULL) {
-                       res = strdup(rpm_pkg->pkg_name);
-                       break;
-               }
+       FILE *f = fopen(out_path, "w");
+       if (f == NULL) {
+               _E("Failed to open file for writing %s: %m", out_path);
+               return;
        }
 
-       free(app_name);
-       return res;
-}
-
-void get_and_save_so_info(char *map_path, char *out_path)
-{
        GSList *file_list = get_filepaths(map_path);
-       GSList *tpk_list = NULL;
-
-       char *rpm_info;
-       FILE *f = fopen(out_path, "w");
+       GSList *pkgs_not_found = NULL;
 
        rpmts ts = init_rpm();
 
-       if (f == NULL) {
-               _E("Failed to open file for writing %s: %m", out_path);
-       } else {
-               char *build_id = NULL;
-               for (GSList *iterator = file_list; iterator; iterator = iterator->next) {
-                       char *file_path = (char *)iterator->data;
-
-                       if (get_build_id(file_path, &build_id) <= 0 || build_id == NULL)
-                               continue;
+       for (GSList *iterator = file_list; iterator; iterator = iterator->next) {
+               char *file_path = (char *)iterator->data;
 
-                       int fret;
+               char *build_id = NULL;
+               if (get_build_id(file_path, &build_id) <= 0 || build_id == NULL)
+                       continue;
 
-                       rpm_info = get_rpm_info(ts, file_path);
-                       if (rpm_info == NULL) {
-                               if (tpk_list == NULL)
-                                       tpk_list = create_tpk_list(ts);
-                               if (tpk_list != NULL)
-                                       rpm_info = get_rpm_info_for_tpk(tpk_list, file_path);
+               char *rpm_info = get_rpm_info(ts, file_path);
+               if (rpm_info == NULL) {
+                       struct rpm_info *ri = malloc(sizeof(struct rpm_info));
+                       if (ri == NULL) {
+                               _E("malloc error: %m");
+                               free(build_id);
+                               break;
                        }
-                       if (rpm_info == NULL)
-                               fret = fprintf(f, "%s %s\n", file_path, build_id);
-                       else {
-                               fret = fprintf(f, "%s %s %s\n", file_path, build_id, rpm_info);
-                               free(rpm_info);
+                       ri->file_path = strdup(file_path);
+                       if (ri->file_path == NULL) {
+                               _E("strdup error: %m");
+                               free(build_id);
+                               free(ri);
+                               break;
                        }
-
+                       ri->app_name = get_app_name_from_path(file_path);
+                       ri->build_id = build_id;
+                       ri->rpm_info = NULL;
+                       pkgs_not_found = g_slist_append(pkgs_not_found, ri);
+               } else {
+                       int fret = fprintf(f, "%s %s %s\n", file_path, build_id, rpm_info);
+                       free(rpm_info);
                        free(build_id);
 
                        if (fret < 0) {
-                               _E("Failed to write to file %s", out_path);
+                               _E("Failed to write to file %s: %m", out_path);
                                break;
                        }
                }
-               fclose(f);
        }
 
-       for (GSList *iterator = file_list; iterator; iterator = iterator->next)
-               free(iterator->data);
+       search_for_tpk(ts, pkgs_not_found);
+
+       for (GSList *iterator = pkgs_not_found; iterator; iterator = iterator->next) {
+               struct rpm_info *ri = (struct rpm_info*)iterator->data;
+               int fret;
+
+               if (ri->rpm_info == NULL)
+                       fret = fprintf(f, "%s %s\n", ri->file_path, ri->build_id);
+               else
+                       fret = fprintf(f, "%s %s %s\n", ri->file_path, ri->build_id, ri->rpm_info);
+
+               if (fret < 0)
+                       _E("Failed to write to file %s: %m", out_path);
 
-       for (GSList *iterator = tpk_list; iterator; iterator = iterator->next) {
-               struct rpm_file *rpm = (struct rpm_file*)iterator->data;
-               free(rpm->file_name);
-               free(rpm->pkg_name);
-               free(rpm);
+               rpm_info_free(ri);
        }
 
+       g_slist_free(pkgs_not_found);
+
+       fclose(f);
+
+       for (GSList *iterator = file_list; iterator; iterator = iterator->next)
+               free(iterator->data);
+
        g_slist_free(file_list);
-       g_slist_free(tpk_list);
 
        free_rpm(ts);
 }