bugreport-service: Add PID information as a new type of bugreport 33/293933/4
authorSung-hun Kim <sfoon.kim@samsung.com>
Thu, 1 Jun 2023 07:05:36 +0000 (16:05 +0900)
committerSung-hun Kim <sfoon.kim@samsung.com>
Thu, 29 Jun 2023 03:52:46 +0000 (12:52 +0900)
To prevent unlimited re-executing a crashed app, application manager
(e.g., AMD) needs an information of PID for the crashed app. But it
don't need the full report of it. So, we need to add a method to get
only the PID while using same diagnostics API call for convenience.

At the perspective of caller, it just uses the same diagnostics API
with an argument "PID" to get the PID of the crashed app.

Change-Id: I165ea2e33840bd803ae4319137bb44f7b2c883d3
Signed-off-by: Sung-hun Kim <sfoon.kim@samsung.com>
src/bugreport-service/diagnostics/diagnostics.c
src/bugreport-service/diagnostics/diagnostics.h
src/bugreport-service/diagnostics/diagnostics_dump.c

index 71df306..dfc24b1 100644 (file)
@@ -191,6 +191,8 @@ static bool file_match(const char *file_name, enum diagnostics_entry entry)
                return ends_with(file_name, LOG_FILE_EXT);
        case COREDUMP_TAR:
                return ends_with(file_name, COREDUMPTAR_FILE_EXT);
+       case INFO_PID:
+               return ends_with(file_name, INFO_FILE_EXT);
        default:
                return false;
        }
index 8835ce1..e86e20c 100644 (file)
@@ -29,6 +29,7 @@ enum diagnostics_entry {
        INFO_FILE,
        LOG_FILE,
        COREDUMP_TAR,
+       INFO_PID,
 };
 
 enum diagnostics_metadata {
index bff0b00..0be6237 100644 (file)
@@ -33,7 +33,7 @@
 #include "shared/log.h"
 #include "shared/util.h"
 
-enum BUGREPORT_REPORT_TYPE { BR_UNKNOWN, BR_BUGREPORT, BR_CRASHINFO, BR_CRASHINFO_JSON, BR_COREDUMP_TAR, BR_FULLREPORT };
+enum BUGREPORT_REPORT_TYPE { BR_UNKNOWN, BR_BUGREPORT, BR_CRASHINFO, BR_CRASHINFO_JSON, BR_COREDUMP_TAR, BR_FULLREPORT, BR_PID };
 
 struct report_file {
        char *file_name;
@@ -300,6 +300,141 @@ static struct report_file *find_report_file(const char *ident, struct report_fil
        return NULL;
 }
 
+static bool parse_pid_from_report_file(int report_fd, char *str)
+{
+       FILE *fp;
+       char buff[1024];
+       int pid = -1;
+
+       if (!str)
+               return false;
+
+       fp = fdopen(report_fd, "r");
+       if (!fp) {
+               _E("There is no report file");
+               return false;
+       }
+
+       while (fgets(buff, sizeof(buff), fp)) {
+               if (sscanf(buff, "PID = %d", &pid) == 1)
+                       break;
+       }
+       if (pid < 0) {
+               _E("There is no PID information in the report file");
+               return false;
+       }
+
+       sprintf(str, "%d", pid);
+
+       return true;
+}
+
+static bool write_pid(int fd, int in_fd)
+{
+       char pid[10];
+
+       if (!parse_pid_from_report_file(in_fd, pid)) {
+               dprintf(fd, "Internal error\n");
+               return false;
+       }
+
+       if (write(fd, pid, strlen(pid)) < 0) {
+               dprintf(fd, "Internal error: %m\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool write_blank(int fd)
+{
+       if (write(fd, " ", 1) < 0) {
+               dprintf(fd, "Internal error: %m\n");
+               return false;
+       }
+
+       return true;
+}
+
+static bool write_pids(int fd, long time_from, long time_to)
+{
+       bool result = true;
+       size_t list_count = 0;
+       struct report_file *list = get_reports_from_range(time_from, time_to, &list_count);
+       if (list == NULL) {
+               dprintf(fd, "Internal error\n");
+               return false;
+       }
+
+       for (size_t i = 0; i < list_count; i++) {
+               int nfd = diagnostics_report_get_file(list[i].file_path, INFO_FILE);
+               if (nfd <= 0) {
+                       _I("No INFO_FILE in %s file", list[i].file_path);
+                       dprintf(nfd, "No INFO_FILE in %s\n",  list[i].file_path);
+                       continue;
+               }
+
+               if (!write_pid(fd, nfd)) {
+                       _E("write_pid error");
+                       close(nfd);
+                       result = false;
+                       break;
+               }
+
+               close(nfd);
+
+               if (!write_blank(fd)) {
+                       _E("write_blank error");
+                       result = false;
+                       break;
+               }
+       }
+
+       for (size_t i = 0; i < list_count; i++)
+               free_record(&list[i]);
+       free(list);
+
+       return result;
+}
+
+static bool write_single_report(struct report_file *report, int fd, enum diagnostics_entry report_entry, const char *ident)
+{
+       bool result = true;
+       int in_fd = diagnostics_report_get_file(report->file_path, report_entry);
+       if (in_fd < 0) {
+               _E("Can not get report entry: %d from: %s (report ident: %s)",
+                               report_entry, report->file_path, ident);
+               return false;
+       }
+
+       switch (report_entry) {
+       case INFO_PID:
+               if (!write_pid(fd, in_fd)) {
+                       _E("Write pid error");
+                       result = false;
+               }
+               break;
+       case LOG_FILE:
+       case INFO_FILE:
+       case INFO_JSON:
+       case COREDUMP_TAR:
+       case FULL_REPORT:
+               if (copy_bytes(fd, in_fd, NULL) == -1) {
+                       _E("Copy data error");
+                       result = false;
+               }
+               break;
+       default:
+               _E("Unsupported report type: %d", report_entry);
+               result = false;
+               break;
+       }
+
+       if (in_fd > 0)
+               close(in_fd);
+       return result;
+}
+
 static bool write_single_file(int fd, enum BUGREPORT_REPORT_TYPE report_type, const char *ident)
 {
        assert(fd >= 0);
@@ -339,24 +474,16 @@ static bool write_single_file(int fd, enum BUGREPORT_REPORT_TYPE report_type, co
        case BR_FULLREPORT:
                report_entry = FULL_REPORT;
                break;
+       case BR_PID:
+               report_entry = INFO_PID;
+               break;
        default:
                _E("Unsupported report type: %d", report_type);
                result = false;
                goto out;
        }
 
-       int in_fd = diagnostics_report_get_file(report->file_path, report_entry);
-       if (in_fd < 0) {
-               _E("Can not get report type: %d from: %s (report ident: %s)", report_type, report->file_path, ident);
-               result = false;
-               goto out;
-       }
-
-       if (copy_bytes(fd, in_fd, NULL) == -1) {
-               _E("Copy data error");
-               result = false;
-               goto out;
-       }
+       result = write_single_report(report, fd, report_entry, ident);
 out:
        for (size_t i = 0; i < list_count; i++)
                free_record(&list[i]);
@@ -375,7 +502,7 @@ static void diagnostics_print_help(int out_fd)
 {
        dprintf(out_fd, "Usage:\n\n"
        "  dumpsys org.tizen.bugreport-service [--type=<report_type>] [[--last <seconds> |--from <timestamp> [--to <timestamp>]]|[report_ident]]\n\n"
-       "  --type <report_type>    Specify the type of report. Available types: bugreport, crash-info, crash-info-json. Additional types are available\n"
+       "  --type <report_type>    Specify the type of report. Available types: bugreport, crash-info, crash-info-json, pid. Additional types are available\n"
        "                          if single report is specified by <report_ident>: fullreport, coredumptar (default: bugreport).\n"
        "  --last <seconds>        Get reports generated in the last <seconds>.\n"
        "  --from <timestamp>      Get reports generated after specified time.\n"
@@ -478,6 +605,8 @@ static bool diagnostics_call_parse_options(int out_fd, char **params, int params
                                dco->report_type = BR_COREDUMP_TAR;
                        } else if (strcmp(optarg, "fullreport") == 0) {
                                dco->report_type = BR_FULLREPORT;
+                       } else if (strcmp(optarg, "pid") == 0) {
+                               dco->report_type = BR_PID;
                        } else {
                                _E("Incorrect report type: %s", optarg);
                                dprintf(out_fd, "Incorrect report type: %s\n", optarg);
@@ -564,6 +693,9 @@ static void diagnostics_callback(diagnostics_data_h data, char **params, int par
        case BR_FULLREPORT:
                dprintf(fd, "Report type \"fullreport\" requires a specific report with report_ident argument.\n");
                break;
+       case BR_PID:
+               write_pids(fd, dco.from, dco.to);
+               break;
        default:
                _E("Unknown report type\n");
        }