[PATCHv2] Add timeout to callbacks waiting for enough entropy (#1073679)

Vratislav Podzimek vpodzime at redhat.com
Wed Nov 5 08:28:53 UTC 2014


On Tue, 2014-11-04 at 09:29 -0500, Anne Mulhern wrote:
> > diff --git a/pyanaconda/ui/gui/spokes/lib/entropy_dialog.py
> > b/pyanaconda/ui/gui/spokes/lib/entropy_dialog.py
> > index d04b08d..3ad1c74 100644
> > --- a/pyanaconda/ui/gui/spokes/lib/entropy_dialog.py
> > +++ b/pyanaconda/ui/gui/spokes/lib/entropy_dialog.py
> > @@ -20,15 +20,21 @@
> >  #
> >  
> >  import time
> > +import math
> >  
> >  from gi.repository import Gtk, GLib
> >  
> > +from pyanaconda.i18n import P_
> > +from pyanaconda.constants import MAX_ENTROPY_WAIT
> >  from pyanaconda.ui.gui import GUIObject
> >  from pyanaconda.ui.gui.utils import gtk_action_wait
> >  from blivet.util import get_current_entropy
> >  
> >  __all__ = ["run_entropy_dialog"]
> >  
> > +# in milliseconds
> > +LOOP_TIMEOUT = 250
> > +
> >  @gtk_action_wait
> >  def run_entropy_dialog(ksdata, desired_entropy):
> >      """Show dialog with waiting for entropy"""
> > @@ -36,6 +42,8 @@ def run_entropy_dialog(ksdata, desired_entropy):
> >      dialog = EntropyDialog(ksdata, desired_entropy)
> >      dialog.run()
> >  
> > +    return dialog.force_cont
> > +
> >  class EntropyDialog(GUIObject):
> >      builderObjects = ["entropyDialog"]
> >      mainWidgetName = "entropyDialog"
> > @@ -46,10 +54,17 @@ class EntropyDialog(GUIObject):
> >          self._desired_entropy = desired_entropy
> >          self._progress_bar = self.builder.get_object("progressBar")
> >          self._terminate = False
> > +        self._started = 0
> > +        self.force_cont = False
> 
> I guess the pylint error about initializing attributes outside the constructor
> must be suppressed in anaconda, but it still seems to me that it would be reasonable
> to define self._num_loops here.
Fixing locally.

> 
> >  
> >      def run(self):
> >          self.window.show_all()
> > -        GLib.timeout_add(250, self._update_progress)
> > +
> > +        # XXX: Is it better to rely on Gtk running the self._update_progress
> > +        # method every ~250msec or rely on NTP not changing system time
> > right
> > +        # now and use time.time()?
> > +        self._num_loops = 0
> > +        GLib.timeout_add(LOOP_TIMEOUT, self._update_progress)
> >          Gtk.main()
> >          self.window.destroy()
> >  
> > @@ -61,13 +76,21 @@ class EntropyDialog(GUIObject):
> >              # remove the method from idle queue
> >              return False
> >          else:
> > +            self._num_loops += 1
> >              current_entropy = get_current_entropy()
> >              current_fraction = min(float(current_entropy) /
> >              self._desired_entropy, 1.0)
> > +            remaining = (MAX_ENTROPY_WAIT - self._num_loops / (1000 /
> > LOOP_TIMEOUT)) / 60.0
> 
> remaining is probably better like this:
> 
> remaining = (MAX_ENTROPY_WAIT - self._num_loops * (LOOP_TIMEOUT / 1000.0)) / 60.0
> 
> Note that you need to make 1000 non-integer to get the fractional quantity. Decimal
> would do just as well, but the precision is unnecessary.
> 
> In your versionn:
> 
> 1000 / LOOP_TIMEOUT is a correct value if 1000 is divisible by LOOP_TIMEOUT, as it
> is now, but will not work correctly if the value of LOOP_TIMEOUT changes to any non-divisor
> of 1000. So, really, it is necessary to make 1000 a fractional quantity in that version as well.
> 
> Alternatively you could get the difference in milliseconds, divide by 1000 to get whole
> seconds, and then divide by 60.0 to get fractional minutes as:
> 
> (MAX_ENTROPY_WAIT * 1000 - self._num_loops * LOOP_TIMEOUT) / 1000 / 60.0
> 
> That seems the clearest approach to me.
Honestly, I don't care too much. Using this version in a local copy.

> 
> > +
> >              self._progress_bar.set_fraction(current_fraction)
> > +            self._progress_bar.set_text("%(pct)d %% (%(rem)d %(min)s
> > remaining)" % {"pct": (int(current_fraction * 100)),
> > +
> > "rem":
> > math.ceil(remaining),
> > +
> > "min":
> > P_("minute", "minutes", int(remaining))})
> > +
> > +            # if we have enough our time ran out, terminate the dialog, but
> > let
> > +            # the progress_bar refresh in the main loop
> > +            self._terminate = (current_entropy >= self._desired_entropy) or
> > (remaining <= 0)
> >  
> > -            # if we have enough, terminate the dialog, but let the
> > progress_bar
> > -            # refresh in the main loop
> > -            self._terminate = current_entropy >= self._desired_entropy
> > +            self.force_cont = (remaining <= 0)
> >  
> >              # keep updating
> >              return True
> > diff --git a/pyanaconda/ui/lib/entropy.py b/pyanaconda/ui/lib/entropy.py
> > index 1fe5634..451f093 100644
> > --- a/pyanaconda/ui/lib/entropy.py
> > +++ b/pyanaconda/ui/lib/entropy.py
> > @@ -28,12 +28,14 @@ import time
> >  import select
> >  import sys
> >  import termios
> > +import math
> >  
> >  from pyanaconda.progress import progress_message
> > +from pyanaconda.constants import MAX_ENTROPY_WAIT
> >  from pykickstart.constants import DISPLAY_MODE_GRAPHICAL
> >  from blivet.util import get_current_entropy
> >  
> > -from pyanaconda.i18n import _
> > +from pyanaconda.i18n import _, P_
> >  
> >  def wait_for_entropy(msg, desired_entropy, ksdata):
> >      """
> > @@ -43,6 +45,8 @@ def wait_for_entropy(msg, desired_entropy, ksdata):
> >      :type ksdata: pykickstart.base.BaseHandler
> >      :param desired_entropy: entropy level to wait for
> >      :type desired_entropy: int
> > +    :returns: whether to force continuing regardless of the available
> > entropy level
> > +    :rtype: bool
> >  
> >      """
> >  
> > @@ -51,15 +55,17 @@ def wait_for_entropy(msg, desired_entropy, ksdata):
> >          # in some cases
> >          from pyanaconda.ui.gui.spokes.lib.entropy_dialog import
> >          run_entropy_dialog
> >          progress_message(_("The system needs more random data entropy"))
> > -        run_entropy_dialog(ksdata, desired_entropy)
> > +        return run_entropy_dialog(ksdata, desired_entropy)
> >      else:
> > -        _tui_wait(msg, desired_entropy)
> > +        return _tui_wait(msg, desired_entropy)
> >  
> >  def _tui_wait(msg, desired_entropy):
> >      """Tell user we are waiting for entropy"""
> >  
> >      print(msg)
> >      print(_("Entropy can be increased by typing randomly on keyboard"))
> > +    print(_("After %d minutes, the installation will continue regardless of
> > the "
> > +            "amount of available entropy") % MAX_ENTROPY_WAIT)
> 
> divide MAX_ENTROPY_WAIT here by 60 in some way in order to get minutes.
Good catch. I was sure I'll forgot to do it somewhere. Fixing locally.

-- 
Vratislav Podzimek

Anaconda Rider | Red Hat, Inc. | Brno - Czech Republic



More information about the anaconda-patches mailing list