]> git.seodisparate.com - SimpleArchiver/commitdiff
Improve error handling
authorStephen Seo <seo.disparate@gmail.com>
Fri, 19 Jul 2024 03:13:54 +0000 (12:13 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 19 Jul 2024 03:13:54 +0000 (12:13 +0900)
Handle SIGPIPE.

src/archiver.c
src/main.c

index 3cccdd793fa2e560d5ca454c4d41a4ab0b0822da..6e2f2ba2975bb25f69ac74c28382a17fe0160fb9 100644 (file)
@@ -28,6 +28,7 @@
     SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
 #include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <spawn.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 
 #define TEMP_FILENAME_CMP "simple_archiver_compressed_%u.tmp"
 
+int is_sig_pipe_occurred = 0;
+
+void handle_sig_pipe(int sig) {
+  if (sig == SIGPIPE) {
+    is_sig_pipe_occurred = 1;
+  }
+}
+
 typedef struct SDArchiverInternalToWrite {
   void *buf;
   uint64_t size;
@@ -145,6 +154,9 @@ int write_files_fn(void *data, void *ud) {
         return 1;
       }
 
+      // Handle SIGPIPE.
+      signal(SIGPIPE, handle_sig_pipe);
+
       int pipe_into_cmd[2];
       int pipe_outof_cmd[2];
       pid_t compressor_pid;
@@ -219,6 +231,13 @@ int write_files_fn(void *data, void *ud) {
       size_t read_count;
       ssize_t ret;
       while (!write_done || !read_done) {
+        if (is_sig_pipe_occurred) {
+          fprintf(stderr,
+                  "WARNING: Failed to write to compressor (SIGPIPE)! Invalid "
+                  "compressor cmd?\n");
+          return 1;
+        }
+
         // Read from file.
         if (!write_done) {
           if (!write_again) {
@@ -231,10 +250,16 @@ int write_files_fn(void *data, void *ud) {
                 write_again = 1;
               } else {
                 // Error during write.
+                fprintf(stderr,
+                        "WARNING: Failed to write to compressor! Invalid "
+                        "compressor cmd?\n");
                 return 1;
               }
             } else if ((size_t)ret != write_count) {
               // Error during write.
+              fprintf(stderr,
+                      "WARNING: Failed to write to compressor! Invalid "
+                      "compressor cmd?\n");
               return 1;
             } else {
               write_again = 0;
@@ -248,6 +273,9 @@ int write_files_fn(void *data, void *ud) {
               // fprintf(stderr, "write_done\n");
             } else if (ferror(file_fd)) {
               // Error during read file.
+              fprintf(
+                  stderr,
+                  "WARNING: Failed to write to compressor (failed to read)!\n");
               return 1;
             }
           }
@@ -260,6 +288,9 @@ int write_files_fn(void *data, void *ud) {
             read_count = fwrite(read_buf, 1, ret, tmp_fd);
             if (read_count != (size_t)ret) {
               // Write to tmp_fd error.
+              fprintf(stderr,
+                      "WARNING: Failed to read from compressor! Invalid "
+                      "compressor cmd?\n");
               return 1;
             } else {
               // fprintf(stderr, "Written %zd bytes to tmp_fd.\n", read_count);
@@ -274,6 +305,9 @@ int write_files_fn(void *data, void *ud) {
               // Nop.
             } else {
               // Read error.
+              fprintf(stderr,
+                      "WARNING: Failed to read from compressor! Invalid "
+                      "compressor cmd?\n");
               return 1;
             }
           } else {
@@ -282,6 +316,13 @@ int write_files_fn(void *data, void *ud) {
         }
       }
 
+      if (is_sig_pipe_occurred) {
+        fprintf(stderr,
+                "WARNING: Failed to write to compressor (SIGPIPE)! Invalid "
+                "compressor cmd?\n");
+        return 1;
+      }
+
       waitpid(compressor_pid, NULL, 0);
 
       uint16_t u16;
@@ -991,6 +1032,9 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
     SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_MAC ||          \
     SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
         if (is_compressed) {
+          // Handle SIGPIPE.
+          signal(SIGPIPE, handle_sig_pipe);
+
           int pipe_into_cmd[2];
           int pipe_outof_cmd[2];
           pid_t decompressor_pid;
@@ -1025,6 +1069,9 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
               // Failed to spawn compressor.
               close(pipe_into_cmd[1]);
               close(pipe_outof_cmd[0]);
+              fprintf(
+                  stderr,
+                  "WARNING: Failed to start decompressor cmd! Invalid cmd?\n");
               return SDAS_INTERNAL_ERROR;
             }
           } else {
@@ -1077,6 +1124,13 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
           char recv_buf[1024];
           size_t amount_to_read;
           while (!write_pipe_done || !read_pipe_done) {
+            if (is_sig_pipe_occurred) {
+              fprintf(stderr,
+                      "WARNING: Failed to write to decompressor (SIGPIPE)! "
+                      "Invalid decompressor cmd?\n");
+              return 1;
+            }
+
             // Read from file.
             if (!write_pipe_done) {
               if (!write_again && compressed_file_size != 0) {
@@ -1106,10 +1160,16 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
                     write_again = 1;
                   } else {
                     // Error.
+                    fprintf(stderr,
+                            "WARNING: Failed to write to decompressor! Invalid "
+                            "decompressor cmd?\n");
                     return SDAS_INTERNAL_ERROR;
                   }
                 } else {
                   // Should be unreachable, error.
+                  fprintf(stderr,
+                          "WARNING: Failed to write to decompressor! Invalid "
+                          "decompressor cmd?\n");
                   return SDAS_INTERNAL_ERROR;
                 }
               }
@@ -1124,9 +1184,15 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
                   // Success.
                 } else if (ferror(out_f)) {
                   // Error.
+                  fprintf(stderr,
+                          "WARNING: Failed to read from decompressor! Invalid "
+                          "decompressor cmd?\n");
                   return SDAS_INTERNAL_ERROR;
                 } else {
                   // Invalid state, error.
+                  fprintf(stderr,
+                          "WARNING: Failed to read from decompressor! Invalid "
+                          "decompressor cmd?\n");
                   return SDAS_INTERNAL_ERROR;
                 }
               } else if (read_ret == -1) {
@@ -1134,6 +1200,9 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
                   // No bytes to read yet.
                 } else {
                   // Error.
+                  fprintf(stderr,
+                          "WARNING: Failed to read from decompressor! Invalid "
+                          "decompressor cmd?\n");
                   return SDAS_INTERNAL_ERROR;
                 }
               } else if (read_ret == 0) {
@@ -1143,11 +1212,21 @@ int simple_archiver_parse_archive_info(FILE *in_f, int do_extract,
                 free_FILE_helper(&out_f);
               } else {
                 // Invalid state (unreachable?), error.
+                fprintf(stderr,
+                        "WARNING: Failed to read from decompressor! Invalid "
+                        "decompressor cmd?\n");
                 return SDAS_INTERNAL_ERROR;
               }
             }
           }
 
+          if (is_sig_pipe_occurred) {
+            fprintf(stderr,
+                    "WARNING: Failed to write to decompressor (SIGPIPE)! "
+                    "Invalid decompressor cmd?\n");
+            return 1;
+          }
+
           waitpid(decompressor_pid, NULL, 0);
         } else {
           uint64_t compressed_file_size = u64;
index a47804480d2934b2f509babc38c39b499c5a9a62..82efda6781e1cc8303a2d7829636b4653c41c33e 100644 (file)
@@ -90,6 +90,7 @@ int main(int argc, const char **argv) {
     SIMPLE_ARCHIVER_PLATFORM == SIMPLE_ARCHIVER_PLATFORM_LINUX
     if (ret != SDAS_SUCCESS) {
       unlink(parsed.filename);
+      return 3;
     }
 #endif
   } else if ((parsed.flags & 3) == 2) {
@@ -97,7 +98,7 @@ int main(int argc, const char **argv) {
     if (!file) {
       fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n",
               parsed.filename);
-      return 3;
+      return 4;
     }
 
     int ret = simple_archiver_parse_archive_info(file, 0, NULL);
@@ -112,7 +113,7 @@ int main(int argc, const char **argv) {
     if (!file) {
       fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n",
               parsed.filename);
-      return 3;
+      return 5;
     }
 
     __attribute__((cleanup(simple_archiver_free_state)))