From 3a8d98dd902da8b69cff731b3db03c75b176b751 Mon Sep 17 00:00:00 2001 From: Tianjie Xu Date: Mon, 3 Apr 2017 20:01:17 -0700 Subject: Abort the update if there's not enough new data Right now the update stuck in a deadlock if there's less new data than expection. Add some checkers and abort the update if such case happens. Also add a corresponding test. Bug: 36787146 Test: update aborts correctly on bullhead && recovery_component_test passes Change-Id: I914e4a2a4cf157b99ef2fc65bd21c6981e38ca47 --- updater/blockimg.cpp | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'updater/blockimg.cpp') diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index 0f08d17eb..d5c170473 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -149,7 +149,7 @@ static void allocate(size_t size, std::vector& buffer) { class RangeSinkWriter { public: RangeSinkWriter(int fd, const RangeSet& tgt) - : fd_(fd), tgt_(tgt), next_range_(0), current_range_left_(0) { + : fd_(fd), tgt_(tgt), next_range_(0), current_range_left_(0), bytes_written_(0) { CHECK_NE(tgt.size(), static_cast(0)); }; @@ -201,9 +201,14 @@ class RangeSinkWriter { written += write_now; } + bytes_written_ += written; return written; } + size_t BytesWritten() const { + return bytes_written_; + } + private: // The input data. int fd_; @@ -213,6 +218,8 @@ class RangeSinkWriter { size_t next_range_; // The number of bytes to write before moving to the next range. size_t current_range_left_; + // Total bytes written by the writer. + size_t bytes_written_; }; /** @@ -238,6 +245,7 @@ struct NewThreadInfo { ZipEntry entry; RangeSinkWriter* writer; + bool receiver_available; pthread_mutex_t mu; pthread_cond_t cv; @@ -274,9 +282,16 @@ static bool receive_new_data(const uint8_t* data, size_t size, void* cookie) { } static void* unzip_new_data(void* cookie) { - NewThreadInfo* nti = static_cast(cookie); - ProcessZipEntryContents(nti->za, &nti->entry, receive_new_data, nti); - return nullptr; + NewThreadInfo* nti = static_cast(cookie); + ProcessZipEntryContents(nti->za, &nti->entry, receive_new_data, nti); + + pthread_mutex_lock(&nti->mu); + nti->receiver_available = false; + if (nti->writer != nullptr) { + pthread_cond_broadcast(&nti->cv); + } + pthread_mutex_unlock(&nti->mu); + return nullptr; } static int ReadBlocks(const RangeSet& src, std::vector& buffer, int fd) { @@ -1133,6 +1148,12 @@ static int PerformCommandNew(CommandParameters& params) { pthread_cond_broadcast(¶ms.nti.cv); while (params.nti.writer != nullptr) { + if (!params.nti.receiver_available) { + LOG(ERROR) << "missing " << (tgt.blocks() * BLOCKSIZE - params.nti.writer->BytesWritten()) + << " bytes of new data"; + pthread_mutex_unlock(¶ms.nti.mu); + return -1; + } pthread_cond_wait(¶ms.nti.cv, ¶ms.nti.mu); } @@ -1361,6 +1382,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, if (params.canwrite) { params.nti.za = za; params.nti.entry = new_entry; + params.nti.receiver_available = true; pthread_mutex_init(¶ms.nti.mu, nullptr); pthread_cond_init(¶ms.nti.cv, nullptr); -- cgit v1.2.3