• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 2727200046

03 Aug 2026 12:48PM UTC coverage: 81.348% (-0.02%) from 81.367%
2727200046

push

gitlab-ci

LudvigAnderson
fix(update-modules): fail the install when the backup fails

`ret=$?` was read inside `if ! <backup>; then`, where `$?` holds the status
of the negated pipeline and is therefore always 0. Both modules exited 0
before applying the payload, so a failed install was reported to the server
as successful: the destination was left untouched while the new software
version was recorded for it. Capture the status from the command itself
instead.

The directory module is the more exposed of the two, since it backs up the
whole destination directory, so any unrelated file growing there can exhaust
the data partition. Reported from the field with a multi-GB core dump.

Add a pytest suite for the shipped update module scripts, alongside the
existing one for the artifact generators, covering both a failing backup and
a successful install for each module. Ignore the Python test caches while
here, since the new suite is the second pytest directory in the tree.

Ticket: MEN-10021
Changelog: Fixed the directory and single-file Update Modules reporting a deployment as
successful when the destination could not be backed up, leaving the destination unchanged.

(cherry picked from commit 8d6f02c81)
Signed-off-by: Ludvig Szklarz Anderson <ludvig.s.anderson@northern.tech>

8487 of 10433 relevant lines covered (81.35%)

21663.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.64
/src/common/processes/processes.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/processes.hpp>
16

17
#include <common/log.hpp>
18
#include <common/common.hpp>
19

20
namespace mender {
21
namespace common {
22
namespace processes {
23

24
namespace log = mender::common::log;
25

26
const chrono::seconds DEFAULT_GENERATE_LINE_DATA_TIMEOUT {10};
27

28
const ProcessesErrorCategoryClass ProcessesErrorCategory;
29

30
const char *ProcessesErrorCategoryClass::name() const noexcept {
×
31
        return "ProcessesErrorCategory";
×
32
}
33

34
string ProcessesErrorCategoryClass::message(int code) const {
86✔
35
        switch (code) {
86✔
36
        case NoError:
37
                return "Success";
×
38
        case SpawnError:
39
                return "Spawn error";
×
40
        case ProcessAlreadyStartedError:
41
                return "Process already started";
×
42
        case NonZeroExitStatusError:
43
                return "Process returned non-zero exit status";
86✔
44
        }
45
        assert(false);
46
        return "Unknown";
×
47
}
48

49
error::Error MakeError(ProcessesErrorCode code, const string &msg) {
1,818✔
50
        return error::Error(error_condition(code, ProcessesErrorCategory), msg);
1,818✔
51
};
52

53
void OutputHandler::operator()(const char *data, size_t size) {
792✔
54
        if (size == 0) {
792✔
55
                return;
×
56
        }
57
        // Get rid of exactly one trailing newline, if there is one. This is because
58
        // we unconditionally print one at the end of every log line. If the string
59
        // does not contain a trailing newline, add a "{...}" instead, since we
60
        // cannot avoid breaking the line apart then.
61
        string content(data, size);
792✔
62
        if (content.back() == '\n') {
792✔
63
                content.pop_back();
792✔
64
        } else {
65
                content.append("{...}");
×
66
        }
67
        auto lines = mender::common::SplitString(content, "\n");
1,584✔
68
        for (auto line : lines) {
1,613✔
69
                log::Info(prefix + line);
1,642✔
70
        }
71
}
792✔
72

73
} // namespace processes
74
} // namespace common
75
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc