@@ -102,6 +102,54 @@ static void unstack_installation_status(getstatus callback)
102102 } while (ipcmsg .data .status .current != IDLE );
103103}
104104
105+ /* Consume progress events
106+ *
107+ * Returns:
108+ * -1 error
109+ * FAILURE the installation failed
110+ * SUCCESS the installation suceeded
111+ * 0 no event or other events consumed
112+ *
113+ * On error, progressfd is closed and set to -1.
114+ */
115+ static int consume_progress_events (int * progressfd )
116+ {
117+ struct progress_msg progressmsg ;
118+ int ret = -1 ;
119+
120+ /* Wait until the end of the installation (FAILURE or SUCCESS) */
121+ while (1 ) {
122+ int err = progress_ipc_receive_nb (progressfd , & progressmsg );
123+ if (err < 0 ) {
124+ /* Note that progressfd may have been closed by progress_ipc_receive
125+ * and set to -1 */
126+ fprintf (stderr , "progress_ipc_receive_nb failed (%d)\n" , ret );
127+ ret = -1 ;
128+ break ;
129+ } else if (err == 0 ) {
130+ /* no pending message */
131+ ret = 0 ;
132+ break ;
133+ }
134+
135+ if (progressmsg .status == FAILURE || progressmsg .status == SUCCESS ) {
136+ /* We have the final result of the installation */
137+ ret = progressmsg .status ;
138+ break ;
139+ } else {
140+ /* Other status (START, RUN, PROGRESS) */
141+ /* continue consuming messages */
142+ continue ;
143+ }
144+ }
145+
146+ if (ret == -1 && * progressfd >= 0 ) {
147+ close (* progressfd );
148+ * progressfd = -1 ;
149+ }
150+
151+ return ret ;
152+ }
105153
106154static void * swupdate_async_thread (void * data )
107155{
@@ -113,6 +161,8 @@ static void *swupdate_async_thread(void *data)
113161 struct async_lib * rq = (struct async_lib * )data ;
114162 int swupdate_result = FAILURE ;
115163 int progressfd = -1 ;
164+ int ret ;
165+ int early_status = -1 ;
116166
117167 sigemptyset (& sigpipe_mask );
118168 sigaddset (& sigpipe_mask , SIGPIPE );
@@ -122,6 +172,16 @@ static void *swupdate_async_thread(void *data)
122172 swupdate_result = FAILURE ;
123173 goto out ;
124174 }
175+ /* Start listening to progress events, before sending
176+ * the image so that we don't miss the result event.
177+ */
178+ progressfd = progress_ipc_connect (0 /* no reconnect */ );
179+ if (progressfd < 0 ) {
180+ fprintf (stderr , "progress_ipc_connect failed\n" );
181+ ipc_end (rq -> connfd );
182+ goto out ;
183+ }
184+
125185 /* Start writing the image until end */
126186
127187 do {
@@ -136,26 +196,40 @@ static void *swupdate_async_thread(void *data)
136196 goto out ;
137197 }
138198 }
199+ /* Consume progress events so that the pipe does not get full
200+ * and block the daemon */
201+ ret = consume_progress_events (& progressfd );
202+ if (ret == -1 ) {
203+ /* If we cannot get events, then we won't be able to get the result.
204+ * Quit and fail */
205+ fprintf (stderr , "Cannot consume progress events. Fail.\n" );
206+ early_status = FAILURE ;
207+ break ;
208+ } else if (ret == FAILURE || ret == SUCCESS ) {
209+ /* early termination */
210+ fprintf (stderr , "early termination while sending the image: %s\n" ,
211+ ret == SUCCESS ?"SUCCESS" :"FAILURE" );
212+ early_status = ret ;
213+ /* interrupt the transfer */
214+ break ;
215+ }
139216 } while (size > 0 );
140217
141- /* Start listening to progress events, before ipc_end
142- * so that we don't miss the result event.
143- */
144- progressfd = progress_ipc_connect (0 /* no reconnect */ );
145-
146218 ipc_end (rq -> connfd );
147219
148- if (progressfd < 0 ) {
149- fprintf (stderr , "progress_ipc_connect failed\n" );
150- goto out ;
151- }
152-
153220 /*
154221 * Everything sent, wait for completion of the installation
155222 */
156223
157- /* Wait until the end of the installation and get the final result */
158- swupdate_result = inst_wait_for_complete (& progressfd ); /* progressfd closed by the call */
224+ if (early_status >= 0 ) {
225+ swupdate_result = early_status ;
226+ close (progressfd );
227+ progressfd = -1 ;
228+
229+ } else {
230+ /* Wait until the end of the installation and get the final result */
231+ swupdate_result = inst_wait_for_complete (& progressfd ); /* progressfd closed by the call */
232+ }
159233
160234 /*
161235 * Get and print all status lines, for compatibility with legacy programs
0 commit comments