diff --git a/lib/services/systemd.c b/lib/services/systemd.c index b64a9642ea3..ea8599c2c4f 100644 --- a/lib/services/systemd.c +++ b/lib/services/systemd.c @@ -918,10 +918,18 @@ unit_method_complete(DBusPendingCall *pending, void *user_data) CRM_LOG_ASSERT(pending == op->opaque->pending); services_set_op_pending(op, NULL); - /* Determine result and finalize action. Start actions must be finalized - * by the registered systemd callback (for instance, handle_systemd_job_complete - * in the executor) to allow for some place to react to the finished - * action before finalizing it and cleaning it up. + /* Determine result and finalize action. + * + * Start and stop actions must be finalized by the registered systemd + * callback (for instance, handle_systemd_job_complete() in the executor) to + * allow for some place to react to the finished action before finalizing it + * and cleaning it up. + * + * HOWEVER, if the operation failed with NOT_INSTALLED, we need to finalize + * it right now too. We'll never receive a JobRemoved() signal for that + * case, so the callback will never be called. Additionally since we set up + * an override file, LoadUnit will always succeed so we can't finalize based + * on that failing. We have to do this here. */ process_unit_method_reply(reply, op); @@ -929,8 +937,9 @@ unit_method_complete(DBusPendingCall *pending, void *user_data) dbus_message_unref(reply); } - if (pcmk__strcase_any_of(op->action, PCMK_ACTION_START, PCMK_ACTION_STOP, - NULL)) { + if ((op->status != PCMK_EXEC_NOT_INSTALLED) + && pcmk__strcase_any_of(op->action, PCMK_ACTION_START, PCMK_ACTION_STOP, + NULL)) { // The filter takes ownership of op and will finalize it on removal if (dbus_connection_add_filter(systemd_proxy, filter_job_removed_signal, op, finalize_async_op_dbus)) {