From time to time, there was an install error raised by swupdate-client when
the daemon processed GET_STATUS too quickly after a REQ_INSTALL:
- when starting, inst.last_install=0, inst.status=IDLE
- swupdate-client:
* sends REQ_INSTALL to the daemon
* ... followed by the payload (the image), which is buffered by the OS
* ... and swupdate-client continues its execution whereas the daemon has
not started receiving the payload so far
* sends REQ_STATUS to the daemon to get the progress status
- swupdate daemon:
* receives REQ_INSTALL and sends ACK
* (1) receives GET_STATUS and answers with inst.last_install=0,
inst.status=IDLE
* (2) notifies another thread that sets inst.status=RUN and proceeds with
the installation
- swupdate-client:
* receives GET_STATUS with inst.last_install=0, inst.status=IDLE
* ... and considers this as a failure, and exits with code 1 (error)
- swupdate daemon:
* continues normally and succeeds
The fact that (1) occurs before (2) is the root cause of the issue as it gives
a wrong information to the client.
It happens when the thread "network_thread" re-acquires the mutex before
pthread_cond_wait (in the thread "network_initializer") re-acquires it himself
(the re-acquiring of the mutex is not said atomic in the man page).
This has been seen on some machines with a swu image of 20480 bytes.
Other improvements:
- remove useless stream_wkup
- move locking to before starting the other thread in order not to miss the
first signal
- do not release the mutex between status=IDLE and pthread_cond_wait in order
not to miss a signal
Signed-off-by: Frederic Hoerni <
fho...@witekio.com>
---
core/network_thread.c | 4 +++-
core/stream_interface.c | 24 ++++++++++--------------
include/network_interface.h | 1 -
3 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/core/network_thread.c b/core/network_thread.c
index d7b713fb..e033f3ab 100644
--- a/core/network_thread.c
+++ b/core/network_thread.c
@@ -486,8 +486,10 @@ void *network_thread (void *data)
/* Drop all old notification from last run */
cleanum_msg_list();
+ /* Switch to RUN */
+ instp->status = RUN;
+
/* Wake-up the installer */
- stream_wkup = true;
pthread_cond_signal(&stream_cond);
} else {
msg.type = NACK;
diff --git a/core/stream_interface.c b/core/stream_interface.c
index 5f3ad2e3..59449815 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -67,7 +67,6 @@ static pthread_t network_thread_id;
* reception of an install request
*
*/
-bool stream_wkup = false;
pthread_mutex_t stream_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t stream_cond = PTHREAD_COND_INITIALIZER;
@@ -533,6 +532,9 @@ void *network_initializer(void *data)
inst.status = IDLE;
inst.software = software;
+ /* Lock in order not to miss the first signal (before pthread_cond_wait) */
+ pthread_mutex_lock(&stream_mutex);
+
/* fork off the local dialogs and network service */
network_thread_id = start_thread(network_thread, &inst);
@@ -543,12 +545,7 @@ void *network_initializer(void *data)
ret = 0;
/* wait for someone to issue an install request */
- pthread_mutex_lock(&stream_mutex);
- while (stream_wkup != true) {
- pthread_cond_wait(&stream_cond, &stream_mutex);
- }
- stream_wkup = false;
- inst.status = RUN;
+ pthread_cond_wait(&stream_cond, &stream_mutex);
pthread_mutex_unlock(&stream_mutex);
notify(START, RECOVERY_NO_ERROR, INFOLEVEL, "Software Update started !");
TRACE("Software update started");
@@ -731,13 +728,6 @@ void *network_initializer(void *data)
swupdate_remove_directory(DATADST_DIR_SUFFIX);
#endif
- pthread_mutex_lock(&stream_mutex);
- inst.status = IDLE;
- inst.req.source = SOURCE_UNKNOWN;
- pthread_mutex_unlock(&stream_mutex);
- TRACE("Main thread sleep again !");
- notify(IDLE, RECOVERY_NO_ERROR, INFOLEVEL, "Waiting for requests...");
-
/*
* Last step, if no restart is required,
* SWUpdate can send automatically the feedback.
@@ -768,6 +758,12 @@ void *network_initializer(void *data)
ipc_send_cmd(&msg);
}
+ pthread_mutex_lock(&stream_mutex);
+ inst.status = IDLE;
+ inst.req.source = SOURCE_UNKNOWN;
+ /* Keep stream_mutex locked until pthread_cond_wait */
+ TRACE("Main thread sleep again !");
+ notify(IDLE, RECOVERY_NO_ERROR, INFOLEVEL, "Waiting for requests...");
}
diff --git a/include/network_interface.h b/include/network_interface.h
index 0a60cad4..53e7fa44 100644
--- a/include/network_interface.h
+++ b/include/network_interface.h
@@ -9,6 +9,5 @@
void *network_initializer(void *data);
void *network_thread(void *data);
-extern bool stream_wkup;
extern pthread_mutex_t stream_mutex;
extern pthread_cond_t stream_cond;
--
2.34.1