blob: ec5bd4f105cb1705d8798414b61fa9e1126ea3e4 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# BitBake ToasterUI Implementation
3# based on (No)TTY UI Implementation by Richard Purdie
4#
5# Handling output to TTYs or files (no TTY)
6#
7# Copyright (C) 2006-2012 Richard Purdie
8# Copyright (C) 2013 Intel Corporation
9#
Brad Bishopc342db32019-05-15 21:57:59 -040010# SPDX-License-Identifier: GPL-2.0-only
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011#
Patrick Williamsc124f4f2015-09-15 14:41:29 -050012
13from __future__ import division
Patrick Williamsf1e5d692016-03-30 15:21:19 -050014import time
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015import sys
16try:
17 import bb
18except RuntimeError as exc:
19 sys.exit(str(exc))
20
21from bb.ui import uihelper
22from bb.ui.buildinfohelper import BuildInfoHelper
23
24import bb.msg
25import logging
26import os
27
28# pylint: disable=invalid-name
29# module properties for UI modules are read by bitbake and the contract should not be broken
30
31
Patrick Williamsc0f7c042017-02-23 20:41:17 -060032featureSet = [bb.cooker.CookerFeatures.HOB_EXTRA_CACHES, bb.cooker.CookerFeatures.BASEDATASTORE_TRACKING, bb.cooker.CookerFeatures.SEND_SANITYEVENTS]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050033
34logger = logging.getLogger("ToasterLogger")
35interactive = sys.stdout.isatty()
36
Patrick Williamsc124f4f2015-09-15 14:41:29 -050037def _log_settings_from_server(server):
38 # Get values of variables which control our output
39 includelogs, error = server.runCommand(["getVariable", "BBINCLUDELOGS"])
40 if error:
41 logger.error("Unable to get the value of BBINCLUDELOGS variable: %s", error)
42 raise BaseException(error)
43 loglines, error = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
44 if error:
45 logger.error("Unable to get the value of BBINCLUDELOGS_LINES variable: %s", error)
46 raise BaseException(error)
47 consolelogfile, error = server.runCommand(["getVariable", "BB_CONSOLELOG"])
48 if error:
49 logger.error("Unable to get the value of BB_CONSOLELOG variable: %s", error)
50 raise BaseException(error)
Patrick Williamsf1e5d692016-03-30 15:21:19 -050051 return consolelogfile
Patrick Williamsc124f4f2015-09-15 14:41:29 -050052
Patrick Williamsf1e5d692016-03-30 15:21:19 -050053# create a log file for a single build and direct the logger at it;
54# log file name is timestamped to the millisecond (depending
55# on system clock accuracy) to ensure it doesn't overlap with
56# other log file names
57#
58# returns (log file, path to log file) for a build
59def _open_build_log(log_dir):
60 format_str = "%(levelname)s: %(message)s"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050061
Patrick Williamsf1e5d692016-03-30 15:21:19 -050062 now = time.time()
63 now_ms = int((now - int(now)) * 1000)
64 time_str = time.strftime('build_%Y%m%d_%H%M%S', time.localtime(now))
65 log_file_name = time_str + ('.%d.log' % now_ms)
66 build_log_file_path = os.path.join(log_dir, log_file_name)
67
68 build_log = logging.FileHandler(build_log_file_path)
69
70 logformat = bb.msg.BBLogFormatter(format_str)
71 build_log.setFormatter(logformat)
72
73 bb.msg.addDefaultlogFilter(build_log)
74 logger.addHandler(build_log)
75
76 return (build_log, build_log_file_path)
77
78# stop logging to the build log if it exists
79def _close_build_log(build_log):
80 if build_log:
81 build_log.flush()
82 build_log.close()
83 logger.removeHandler(build_log)
84
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050085_evt_list = [
86 "bb.build.TaskBase",
87 "bb.build.TaskFailed",
88 "bb.build.TaskFailedSilent",
89 "bb.build.TaskStarted",
90 "bb.build.TaskSucceeded",
91 "bb.command.CommandCompleted",
92 "bb.command.CommandExit",
93 "bb.command.CommandFailed",
94 "bb.cooker.CookerExit",
Patrick Williamsc0f7c042017-02-23 20:41:17 -060095 "bb.event.BuildInit",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050096 "bb.event.BuildCompleted",
97 "bb.event.BuildStarted",
98 "bb.event.CacheLoadCompleted",
99 "bb.event.CacheLoadProgress",
100 "bb.event.CacheLoadStarted",
101 "bb.event.ConfigParsed",
102 "bb.event.DepTreeGenerated",
103 "bb.event.LogExecTTY",
104 "bb.event.MetadataEvent",
105 "bb.event.MultipleProviders",
106 "bb.event.NoProvider",
107 "bb.event.ParseCompleted",
108 "bb.event.ParseProgress",
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600109 "bb.event.ParseStarted",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500110 "bb.event.RecipeParsed",
111 "bb.event.SanityCheck",
112 "bb.event.SanityCheckPassed",
113 "bb.event.TreeDataPreparationCompleted",
114 "bb.event.TreeDataPreparationStarted",
115 "bb.runqueue.runQueueTaskCompleted",
116 "bb.runqueue.runQueueTaskFailed",
117 "bb.runqueue.runQueueTaskSkipped",
118 "bb.runqueue.runQueueTaskStarted",
119 "bb.runqueue.sceneQueueTaskCompleted",
120 "bb.runqueue.sceneQueueTaskFailed",
121 "bb.runqueue.sceneQueueTaskStarted",
122 "logging.LogRecord"]
123
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500124def main(server, eventHandler, params):
125 # set to a logging.FileHandler instance when a build starts;
126 # see _open_build_log()
127 build_log = None
128
129 # set to the log path when a build starts
130 build_log_file_path = None
131
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500132 helper = uihelper.BBUIHelper()
133
Andrew Geissler4c19ea12020-10-27 13:52:24 -0500134 if not params.observe_only:
135 params.updateToServer(server, os.environ.copy())
136 params.updateFromServer(server)
137
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500138 # TODO don't use log output to determine when bitbake has started
139 #
140 # WARNING: this log handler cannot be removed, as localhostbecontroller
141 # relies on output in the toaster_ui.log file to determine whether
142 # the bitbake server has started, which only happens if
143 # this logger is setup here (see the TODO in the loop below)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500144 console = logging.StreamHandler(sys.stdout)
145 format_str = "%(levelname)s: %(message)s"
146 formatter = bb.msg.BBLogFormatter(format_str)
147 bb.msg.addDefaultlogFilter(console)
148 console.setFormatter(formatter)
149 logger.addHandler(console)
150 logger.setLevel(logging.INFO)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500151 llevel, debug_domains = bb.msg.constructLogOptions()
152 result, error = server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])
153 if not result or error:
154 logger.error("can't set event mask: %s", error)
155 return 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500156
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500157 # verify and warn
158 build_history_enabled = True
159 inheritlist, _ = server.runCommand(["getVariable", "INHERIT"])
160
161 if not "buildhistory" in inheritlist.split(" "):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600162 logger.warning("buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163 build_history_enabled = False
164
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500165 if not "buildstats" in inheritlist.split(" "):
166 logger.warning("buildstats is not enabled. Please enable INHERIT += \"buildstats\" to generate build statistics.")
167
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500168 if not params.observe_only:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500169 cmdline = params.parseActions()
170 if not cmdline:
171 print("Nothing to do. Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
172 return 1
173 if 'msg' in cmdline and cmdline['msg']:
174 logger.error(cmdline['msg'])
175 return 1
176
177 ret, error = server.runCommand(cmdline['action'])
178 if error:
179 logger.error("Command '%s' failed: %s" % (cmdline, error))
180 return 1
Andrew Geissler82c905d2020-04-13 13:39:40 -0500181 elif not ret:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500182 logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
183 return 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500184
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500185 # set to 1 when toasterui needs to shut down
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500186 main.shutdown = 0
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500187
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500188 interrupted = False
189 return_value = 0
190 errors = 0
191 warnings = 0
192 taskfailures = []
193 first = True
194
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500195 buildinfohelper = BuildInfoHelper(server, build_history_enabled,
196 os.getenv('TOASTER_BRBE'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500198 # write our own log files into bitbake's log directory;
199 # we're only interested in the path to the parent directory of
200 # this file, as we're writing our own logs into the same directory
201 consolelogfile = _log_settings_from_server(server)
202 log_dir = os.path.dirname(consolelogfile)
203 bb.utils.mkdirhier(log_dir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500204
205 while True:
206 try:
207 event = eventHandler.waitEvent(0.25)
208 if first:
209 first = False
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500210
211 # TODO don't use log output to determine when bitbake has started
212 #
213 # this is the line localhostbecontroller needs to
214 # see in toaster_ui.log which it uses to decide whether
215 # the bitbake server has started...
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500216 logger.info("ToasterUI waiting for events")
217
218 if event is None:
219 if main.shutdown > 0:
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500220 # if shutting down, close any open build log first
221 _close_build_log(build_log)
222
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 break
224 continue
225
226 helper.eventHandler(event)
227
228 # pylint: disable=protected-access
229 # the code will look into the protected variables of the event; no easy way around this
230
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500231 if isinstance(event, bb.event.HeartbeatEvent):
232 continue
233
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500234 if isinstance(event, bb.event.ParseStarted):
235 if not (build_log and build_log_file_path):
236 build_log, build_log_file_path = _open_build_log(log_dir)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600237
238 buildinfohelper.store_started_build()
239 buildinfohelper.save_build_log_file_path(build_log_file_path)
240 buildinfohelper.set_recipes_to_parse(event.total)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500241 continue
242
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600243 # create a build object in buildinfohelper from either BuildInit
244 # (if available) or BuildStarted (for jethro and previous versions)
245 if isinstance(event, (bb.event.BuildStarted, bb.event.BuildInit)):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500246 if not (build_log and build_log_file_path):
247 build_log, build_log_file_path = _open_build_log(log_dir)
248
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600249 buildinfohelper.save_build_targets(event)
250 buildinfohelper.save_build_log_file_path(build_log_file_path)
251
252 # get additional data from BuildStarted
253 if isinstance(event, bb.event.BuildStarted):
254 buildinfohelper.save_build_layers_and_variables()
255 continue
256
257 if isinstance(event, bb.event.ParseProgress):
258 buildinfohelper.set_recipes_parsed(event.current)
259 continue
260
261 if isinstance(event, bb.event.ParseCompleted):
262 buildinfohelper.set_recipes_parsed(event.total)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500263 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500264
265 if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded, bb.build.TaskFailedSilent)):
266 buildinfohelper.update_and_store_task(event)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500267 logger.info("Logfile for task %s", event.logfile)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500268 continue
269
270 if isinstance(event, bb.build.TaskBase):
271 logger.info(event._message)
272
273 if isinstance(event, bb.event.LogExecTTY):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500274 logger.info(event.msg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500275 continue
276
277 if isinstance(event, logging.LogRecord):
278 if event.levelno == -1:
279 event.levelno = formatter.ERROR
280
281 buildinfohelper.store_log_event(event)
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500282
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500283 if event.levelno >= formatter.ERROR:
284 errors = errors + 1
285 elif event.levelno == formatter.WARNING:
286 warnings = warnings + 1
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500287
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288 # For "normal" logging conditions, don't show note logs from tasks
289 # but do show them if the user has changed the default log level to
290 # include verbose/debug messages
291 if event.taskpid != 0 and event.levelno <= formatter.NOTE:
292 continue
293
294 logger.handle(event)
295 continue
296
297 if isinstance(event, bb.build.TaskFailed):
298 buildinfohelper.update_and_store_task(event)
299 logfile = event.logfile
300 if logfile and os.path.exists(logfile):
301 bb.error("Logfile of failure stored in: %s" % logfile)
302 continue
303
304 # these events are unprocessed now, but may be used in the future to log
305 # timing and error informations from the parsing phase in Toaster
306 if isinstance(event, (bb.event.SanityCheckPassed, bb.event.SanityCheck)):
307 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500308 if isinstance(event, bb.event.CacheLoadStarted):
309 continue
310 if isinstance(event, bb.event.CacheLoadProgress):
311 continue
312 if isinstance(event, bb.event.CacheLoadCompleted):
313 continue
314 if isinstance(event, bb.event.MultipleProviders):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500315 logger.info(str(event))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500316 continue
317
318 if isinstance(event, bb.event.NoProvider):
319 errors = errors + 1
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500320 text = str(event)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500321 logger.error(text)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500322 buildinfohelper.store_log_error(text)
323 continue
324
325 if isinstance(event, bb.event.ConfigParsed):
326 continue
327 if isinstance(event, bb.event.RecipeParsed):
328 continue
329
330 # end of saved events
331
332 if isinstance(event, (bb.runqueue.sceneQueueTaskStarted, bb.runqueue.runQueueTaskStarted, bb.runqueue.runQueueTaskSkipped)):
333 buildinfohelper.store_started_task(event)
334 continue
335
336 if isinstance(event, bb.runqueue.runQueueTaskCompleted):
337 buildinfohelper.update_and_store_task(event)
338 continue
339
340 if isinstance(event, bb.runqueue.runQueueTaskFailed):
341 buildinfohelper.update_and_store_task(event)
342 taskfailures.append(event.taskstring)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500343 logger.error(str(event))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500344 continue
345
346 if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted, bb.runqueue.sceneQueueTaskFailed)):
347 buildinfohelper.update_and_store_task(event)
348 continue
349
350
351 if isinstance(event, (bb.event.TreeDataPreparationStarted, bb.event.TreeDataPreparationCompleted)):
352 continue
353
354 if isinstance(event, (bb.event.BuildCompleted, bb.command.CommandFailed)):
355
356 errorcode = 0
357 if isinstance(event, bb.command.CommandFailed):
358 errors += 1
359 errorcode = 1
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500360 logger.error(str(event))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600361 elif isinstance(event, bb.event.BuildCompleted):
362 buildinfohelper.scan_image_artifacts()
363 buildinfohelper.clone_required_sdk_artifacts()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500364
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500365 # turn off logging to the current build log
366 _close_build_log(build_log)
367
368 # reset ready for next BuildStarted
369 build_log = None
370
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 # update the build info helper on BuildCompleted, not on CommandXXX
372 buildinfohelper.update_build_information(event, errors, warnings, taskfailures)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500373
374 brbe = buildinfohelper.brbe
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375 buildinfohelper.close(errorcode)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500376
377 # we start a new build info
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500378 if params.observe_only:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500379 logger.debug("ToasterUI prepared for new build")
380 errors = 0
381 warnings = 0
382 taskfailures = []
383 buildinfohelper = BuildInfoHelper(server, build_history_enabled)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500384 else:
385 main.shutdown = 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500386
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500387 logger.info("ToasterUI build done, brbe: %s", brbe)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500388 continue
389
390 if isinstance(event, (bb.command.CommandCompleted,
391 bb.command.CommandFailed,
392 bb.command.CommandExit)):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500393 if params.observe_only:
394 errorcode = 0
395 else:
396 main.shutdown = 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397
398 continue
399
400 if isinstance(event, bb.event.MetadataEvent):
401 if event.type == "SinglePackageInfo":
402 buildinfohelper.store_build_package_information(event)
403 elif event.type == "LayerInfo":
404 buildinfohelper.store_layer_info(event)
405 elif event.type == "BuildStatsList":
406 buildinfohelper.store_tasks_stats(event)
407 elif event.type == "ImagePkgList":
408 buildinfohelper.store_target_package_data(event)
409 elif event.type == "MissedSstate":
410 buildinfohelper.store_missed_state_tasks(event)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600411 elif event.type == "SDKArtifactInfo":
412 buildinfohelper.scan_sdk_artifacts(event)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500413 elif event.type == "SetBRBE":
414 buildinfohelper.brbe = buildinfohelper._get_data_from_event(event)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600415 elif event.type == "TaskArtifacts":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500416 buildinfohelper.scan_task_artifacts(event)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500417 elif event.type == "OSErrorException":
418 logger.error(event)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500419 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600420 logger.error("Unprocessed MetadataEvent %s", event.type)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421 continue
422
423 if isinstance(event, bb.cooker.CookerExit):
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500424 # shutdown when bitbake server shuts down
425 main.shutdown = 1
426 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500427
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500428 if isinstance(event, bb.event.DepTreeGenerated):
429 buildinfohelper.store_dependency_information(event)
430 continue
431
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600432 logger.warning("Unknown event: %s", event)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500433 return_value += 1
434
435 except EnvironmentError as ioerror:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600436 logger.warning("EnvironmentError: %s" % ioerror)
437 # ignore interrupted io system calls
438 if ioerror.args[0] == 4: # errno 4 is EINTR
439 logger.warning("Skipped EINTR: %s" % ioerror)
440 else:
441 raise
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500442 except KeyboardInterrupt:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600443 if params.observe_only:
444 print("\nKeyboard Interrupt, exiting observer...")
445 main.shutdown = 2
446 if not params.observe_only and main.shutdown == 1:
447 print("\nSecond Keyboard Interrupt, stopping...\n")
448 _, error = server.runCommand(["stateForceShutdown"])
449 if error:
450 logger.error("Unable to cleanly stop: %s" % error)
451 if not params.observe_only and main.shutdown == 0:
452 print("\nKeyboard Interrupt, closing down...\n")
453 interrupted = True
454 _, error = server.runCommand(["stateShutdown"])
455 if error:
456 logger.error("Unable to cleanly shutdown: %s" % error)
457 buildinfohelper.cancel_cli_build()
458 main.shutdown = main.shutdown + 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 except Exception as e:
460 # print errors to log
461 import traceback
462 from pprint import pformat
463 exception_data = traceback.format_exc()
464 logger.error("%s\n%s" , e, exception_data)
465
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500466 # save them to database, if possible; if it fails, we already logged to console.
467 try:
468 buildinfohelper.store_log_exception("%s\n%s" % (str(e), exception_data))
469 except Exception as ce:
470 logger.error("CRITICAL - Failed to to save toaster exception to the database: %s", str(ce))
471
472 # make sure we return with an error
473 return_value += 1
474
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500475 if interrupted and return_value == 0:
476 return_value += 1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500477
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600478 logger.warning("Return value is %d", return_value)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500479 return return_value