| 719 | } |
| 720 | |
| 721 | bool createSystemdUnit(const QString &name, const VariantList &propList) |
| 722 | { |
| 723 | using namespace Qt::StringLiterals; |
| 724 | |
| 725 | const QList<QVariant> args({name, u"fail"_s, QVariant::fromValue(propList), QVariant::fromValue(EmptyArray())}); |
| 726 | |
| 727 | auto message = callSmdDBus(u"/org/freedesktop/systemd1"_s, u"Manager"_s, u"StartTransientUnit"_s, args); |
| 728 | if (message.type() == QDBusMessage::ErrorMessage) { |
| 729 | return false; |
| 730 | } |
| 731 | |
| 732 | auto reply = QDBusReply<QDBusObjectPath>(message); |
| 733 | if (!reply.isValid()) { |
| 734 | return false; |
| 735 | } |
| 736 | |
| 737 | auto path = reply.value(); |
| 738 | |
| 739 | // Wait for the job to finish |
| 740 | // We really should be listening for the "JobRemoved" signal of systemd's Manager object, |
| 741 | // but that is hard as it makes things async, so instead just wait for the job object to |
| 742 | // disappear and if it does, assume the job finished successfully. |
| 743 | int tries = 10; |
| 744 | bool jobExists = true; |
| 745 | while (tries > 0) { |
| 746 | const auto jobArgs = QList<QVariant>{u"org.freedesktop.systemd1.Job"_s, u"State"_s}; |
| 747 | auto jobReply = callSmdDBus(path.path(), u"Properties"_s, u"Get"_s, jobArgs, u"org.freedesktop.DBus"_s); |
| 748 | if (jobReply.type() == QDBusMessage::ErrorMessage) { |
| 749 | jobExists = false; |
| 750 | break; |
| 751 | } |
| 752 | |
| 753 | QThread::sleep(std::chrono::milliseconds(10)); |
| 754 | tries--; |
| 755 | } |
| 756 | |
| 757 | return !jobExists; |
| 758 | } |
| 759 | |
| 760 | bool createCGroup(const QString &name, int initialPid) |
| 761 | { |