LCOV - code coverage report
Current view: top level - machine - operation.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 76 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 3 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <sys/wait.h>
       4             : 
       5             : #include "alloc-util.h"
       6             : #include "fd-util.h"
       7             : #include "operation.h"
       8             : #include "process-util.h"
       9             : 
      10           0 : static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
      11           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
      12           0 :         Operation *o = userdata;
      13             :         int r;
      14             : 
      15           0 :         assert(o);
      16           0 :         assert(si);
      17             : 
      18           0 :         log_debug("Operating " PID_FMT " is now complete with code=%s status=%i",
      19             :                   o->pid,
      20             :                   sigchld_code_to_string(si->si_code), si->si_status);
      21             : 
      22           0 :         o->pid = 0;
      23             : 
      24           0 :         if (si->si_code != CLD_EXITED) {
      25           0 :                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
      26           0 :                 goto fail;
      27             :         }
      28             : 
      29           0 :         if (si->si_status == EXIT_SUCCESS)
      30           0 :                 r = 0;
      31           0 :         else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */
      32           0 :                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed.");
      33           0 :                 goto fail;
      34             :         }
      35             : 
      36           0 :         if (o->done) {
      37             :                 /* A completion routine is set for this operation, call it. */
      38           0 :                 r = o->done(o, r, &error);
      39           0 :                 if (r < 0) {
      40           0 :                         if (!sd_bus_error_is_set(&error))
      41           0 :                                 sd_bus_error_set_errno(&error, r);
      42             : 
      43           0 :                         goto fail;
      44             :                 }
      45             : 
      46             :         } else {
      47             :                 /* The default operation when done is to simply return an error on failure or an empty success
      48             :                  * message on success. */
      49           0 :                 if (r < 0) {
      50           0 :                         sd_bus_error_set_errno(&error, r);
      51           0 :                         goto fail;
      52             :                 }
      53             : 
      54           0 :                 r = sd_bus_reply_method_return(o->message, NULL);
      55           0 :                 if (r < 0)
      56           0 :                         log_error_errno(r, "Failed to reply to message: %m");
      57             :         }
      58             : 
      59           0 :         operation_free(o);
      60           0 :         return 0;
      61             : 
      62           0 : fail:
      63           0 :         r = sd_bus_reply_method_error(o->message, &error);
      64           0 :         if (r < 0)
      65           0 :                 log_error_errno(r, "Failed to reply to message: %m");
      66             : 
      67           0 :         operation_free(o);
      68           0 :         return 0;
      69             : }
      70             : 
      71           0 : int operation_new(Manager *manager, Machine *machine, pid_t child, sd_bus_message *message, int errno_fd, Operation **ret) {
      72             :         Operation *o;
      73             :         int r;
      74             : 
      75           0 :         assert(manager);
      76           0 :         assert(child > 1);
      77           0 :         assert(message);
      78           0 :         assert(errno_fd >= 0);
      79             : 
      80           0 :         o = new0(Operation, 1);
      81           0 :         if (!o)
      82           0 :                 return -ENOMEM;
      83             : 
      84           0 :         o->extra_fd = -1;
      85             : 
      86           0 :         r = sd_event_add_child(manager->event, &o->event_source, child, WEXITED, operation_done, o);
      87           0 :         if (r < 0) {
      88           0 :                 free(o);
      89           0 :                 return r;
      90             :         }
      91             : 
      92           0 :         o->pid = child;
      93           0 :         o->message = sd_bus_message_ref(message);
      94           0 :         o->errno_fd = errno_fd;
      95             : 
      96           0 :         LIST_PREPEND(operations, manager->operations, o);
      97           0 :         manager->n_operations++;
      98           0 :         o->manager = manager;
      99             : 
     100           0 :         if (machine) {
     101           0 :                 LIST_PREPEND(operations_by_machine, machine->operations, o);
     102           0 :                 o->machine = machine;
     103             :         }
     104             : 
     105           0 :         log_debug("Started new operation " PID_FMT ".", child);
     106             : 
     107             :         /* At this point we took ownership of both the child and the errno file descriptor! */
     108             : 
     109           0 :         if (ret)
     110           0 :                 *ret = o;
     111             : 
     112           0 :         return 0;
     113             : }
     114             : 
     115           0 : Operation *operation_free(Operation *o) {
     116           0 :         if (!o)
     117           0 :                 return NULL;
     118             : 
     119           0 :         sd_event_source_unref(o->event_source);
     120             : 
     121           0 :         safe_close(o->errno_fd);
     122           0 :         safe_close(o->extra_fd);
     123             : 
     124           0 :         if (o->pid > 1)
     125           0 :                 (void) sigkill_wait(o->pid);
     126             : 
     127           0 :         sd_bus_message_unref(o->message);
     128             : 
     129           0 :         if (o->manager) {
     130           0 :                 LIST_REMOVE(operations, o->manager->operations, o);
     131           0 :                 o->manager->n_operations--;
     132             :         }
     133             : 
     134           0 :         if (o->machine)
     135           0 :                 LIST_REMOVE(operations_by_machine, o->machine->operations, o);
     136             : 
     137           0 :         return mfree(o);
     138             : }

Generated by: LCOV version 1.14