Quit after n seconds

2009-06-01
2013-05-28
  • Sean Robinson
    Sean Robinson
    2009-06-01

    Hello, I am trying to modify the source code to quit the program after n number of seconds, but thus far I cannot figure where such code should go.  For reference, this is what I'm currently trying:

        def run(self):
            # automatically stop the program after so many SECONDS
            totalRunTime = 4.0
            startTime = time.time()
            while not self.finished.isSet():
                if self.ControlKeyHash.check():
                    if not self.mainapp.panel:
                        self.lw.PrintDebug("starting panel")
                        self.mainapp.panel = True
                        self.ControlKeyHash.reset()
                        PyKeyloggerControlPanel(self.cmdoptions, self.mainapp)
                time.sleep(0.05)
                if time.time() - startTime >= totalRunTime:
                    cancel()

     
    • nanotube
      nanotube
      2009-06-01

      Hi,
      First, ControlKeyMonitor only gets used on linux - so if you're on windows, you're wasting your time there.

      For linux, indeed, you chose a nice place - but instead of "cancel()" - which is not defined, call "self.mainapp.stop()" to quit.

      for windows (this would work for both win and lin, though), same functionality is in the keylogger.onkeydownevent method, just call self.stop() with your time condition somewhere at the beginning of that method.

      the problem with the latter method is that the program won't exit until time is up /and/ a key is pressed, since that function only executes when a key is pressed.

      hope that helps.

      out of curiosity, why do you need this?

      also, note that time.time counts in milliseconds. so if you set it to quit after "4.0" you are specifying 4 milliseconds. just so you are aware. :)

       
      • Sean Robinson
        Sean Robinson
        2009-06-02

        My main purpose is just to have the program run for a specified period of time instead of all the time and to quit silently without the need of user interaction.  For example, I imagine a person might want his work documented but not his leisure or vice versa, and a company implementing this wouldn't want the common employees to have to know or interface with the program beyond them being aware of its presence, let alone the password.

        Just a correction, but according to the official Python documentation located here [ http://www.python.org/doc/2.5.4/lib/module-time.html ], time.time() is seconds since the epoch.  It has been this way in at least versions 2.4, 2.5, and 2.6.

         
      • Sean Robinson
        Sean Robinson
        2009-06-02

        OK, I did the modifications like you suggested, and et voila, it works as prescribed - after the user presses a key after the elapsed set time period, the program closes and writes the log to file.

        But there is one small problem: if the program is run from a command line, and focus is not changed to another window, when the program closes, it spits out this error message set:

        ---
        Exception in thread Thread-4 (most likely raised during interpreter shutdown):
        Traceback (most recent call last):
        Exception in thread Thread-1 (most likely raised during interpreter shutdown):
        Traceback (most recent call last):
          File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
          File "C:\My Documents\downloads\pykeylogger-1.0.4\logwriter.py", line 212, in
        run
        <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
        Unhandled exception in thread started by
        Error in sys.excepthook:

        Original exception was:
        ---

        And yes, that last line is actually empty after the colon - there is no location of original exception.

         
    • nanotube
      nanotube
      2009-06-01

      also just to make sure you don't miss this - if you use onkeydownevent, you have to define the start time outside of that function scope, otherwise it would get reset. somewhere in keylogger.__init__ you could define a self.starttime, or something like that.

       
    • nanotube
      nanotube
      2009-06-02

      Hi,
      my bad, indeed time.time is in seconds. ;)

      interesting idea you have, but as far as the approach, seems a bit too invariant. usually a person would work for an hour or two, then take a brief break, then work for another stretch, then take another break, etc. the work times and break times would be entirely variant. so generally, i think you would /want/ some user interaction.

      for your use case, i'd think a separate shortcut key that turns on and off the logging, without exiting the keylogger, would be what you're looking for. so a user works, then says ah, need a break, presses the turn off logging shortcut, does his personal stuff, then presses the shortcut again, and starts back on work stuff.

      just a thought :)

       
    • nanotube
      nanotube
      2009-06-02

      yea, sometimes weird things happen on exit, because of all the threads running.

      at the top, try adding a line "from Queue import Empty"
      and then change line 212 in logwriter from "except Queue.Empty" to "except Empty" , and see if that helps with this one...

       
      • Sean Robinson
        Sean Robinson
        2009-06-03

        Ta-da, your advice worked like a charm - it didn't at first though, but then I realized I needed to put "from Queue import Empty" after "import Queue" instead of before it. :)  Good thing too, since if you have the error I was getting, you sometimes get a log file with a bunch of junk characters in it and I don't believe that successive sessions would cause it to get correctly written to either.

        Anyway, though, it is an edge case.  Thanks for your help!

         
        • nanotube
          nanotube
          2009-06-03

          sounds great! ;)

          i just pushed this fix to the git repo.

          by the way, i suggest you pull the latest code from git, since i have made a bunch of bugfixes since v 1.0.4 (primarily unicode fixes), and by your line number in the exception, i see that you're using the 1.0.4 release.

          one of these days i'll get around to making the 1.0.5 release... :)

           
          • Sean Robinson
            Sean Robinson
            2009-06-04

            I took your advice and checked out the source from git (adding my modifications in too, of course), and I have to say, "Ooh, so close!" in regards to your bug fix.  The line "from Queue import Empty" shouldn't go into logwriter.py, where it currently is.  The line should go into keylogger.pyw after the "import Queue" line.  That will stop the thread exception messages.

             
            • nanotube
              nanotube
              2009-06-04

              Thanks for the note!

              did that and committed the fix - please give it another try, just to make sure :)

               
              • Sean Robinson
                Sean Robinson
                2009-06-06

                Looks like all this Empty vs. Queue.Empty makes no difference - many of the error message occur due to your try/except blocks not handling NULL data that is sometimes sent to them.  Then if the program tries to output sys.exc_info(), there is none from the NULL data, and that causes a further error.  So imagecapture.py and logwriter.py, which are two that usually have this problem, should make sure to have a catch for NULL data's exceptions with a simple "except:" statement.

                I've also noticed that the program crashes at the end when too much text is written too quickly but it still logs what was written.  Try running the program and going mashity-mashity on the keyboard to see what I mean.

                 
                • nanotube
                  nanotube
                  2009-06-07

                  Would you be kind enough to paste some tracebacks of the errors you are describing?

                  Also... i'll try the mashity-mashity thing and see what happens... but please clarify for me - are you saying you are going mashity-mashity, then quitting immediately? (because you said "at the end") or does that happen without quitting?

                  also, are you doing all this on windows, or linux? and what version of python?

                   
                • nanotube
                  nanotube
                  2009-06-07

                  fyi: just tried the mashity-mashity thing, with no ill effects, here on my linux box...

                   
                • Grahack
                  Grahack
                  2009-06-07

                  Hi, could we find a more precise exception corresponding to the NULL data?
                  Putting a bare 'except:' will raise hidden problem catching other cases.

                   
                  • Sean Robinson
                    Sean Robinson
                    2009-06-07

                    I have the program running on a 2-second timer after which it auto-quits.  I'm running on top of Microsoft Windows XP Professional SP2 and using Python 2.5.4.  Let's see what I can find as far as error messages go.

                    ---
                    Exception in thread Thread-1 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\logwriter.py", line 212, in
                    run
                    <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
                    Unhandled exception in thread started by
                    Error in sys.excepthook:

                    Original exception was:
                    ---

                    ---
                    Exception in thread Thread-1 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\logwriter.py", line 212, in
                    run
                    <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
                    Unhandled exception in thread started by
                    Error in sys.excepthook:

                    Original exception was:
                    Exception in thread Thread-3 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\mytimer.py", line 36, in run

                      File "C:\Python25\lib\threading.py", line 368, in wait
                      File "C:\Python25\lib\threading.py", line 240, in wait
                    <type 'exceptions.ValueError'>: list.remove(x): x not in list
                    Exception in thread Thread-4 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\imagecapture.py", line 112,
                    in run
                    <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
                    Unhandled exception in thread started by
                    Error in sys.excepthook:

                    Original exception was:
                    ---

                    ---
                    Exception in thread Thread-1 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\logwriter.py", line 212, in
                    run
                    <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
                    Exception in thread Thread-4 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\imagecapture.py", line 112,
                    in run
                    <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'Empty'
                    Unhandled exception in thread started by
                    Error in sys.excepthook:

                    Original exception was:
                    Exception in thread Thread-3 (most likely raised during interpreter shutdown):
                    Traceback (most recent call last):
                      File "C:\Python25\lib\threading.py", line 486, in __bootstrap_inner
                      File "C:\My Documents\downloads\pykeylogger-1.0.4\mytimer.py", line 36, in run

                      File "C:\Python25\lib\threading.py", line 368, in wait
                      File "C:\Python25\lib\threading.py", line 240, in wait
                    <type 'exceptions.ValueError'>: list.remove(x): x not in list
                    ---

                    Those are pretty typical of the error messages I've been receiving.

                     
                    • nanotube
                      nanotube
                      2009-06-08

                      Hmm, well... it is encouraging to see that all of them are attributeerrors. seems that there's some funky stuff going on on exit, objects getting destroyed left and right, heh. i'll look into how this can be ameliorated... but at the very least, we could just stick a bunch of "except AttributeError" bits.

                      thanks for all the details you have been providing!  will get back to you with some stuff to test in a bit. :)

                       
                      • nanotube
                        nanotube
                        2009-06-08

                        correction... most of them.
                        on a more careful review, i see there's some stuff happening inside the threading module itself... not sure what we can do about those, but will look around.

                         
                  • nanotube
                    nanotube
                    2009-06-08

                    indeed, that's why i asked for some tracebacks....

                     
    • nanotube
      nanotube
      2009-06-26

      hey!
      so... i've been working on a major code refactoring to make things more logically structured... as a bonus, it should also have eliminated these errors on exit.

      if you have some time, i'd appreciate it if you pull the latest from git from the "refactor_threads" branch, and give it a whirl.

      there's a new dependency now - the pmw library for an enhanced gui. you can get it from pmw.sourceforge.net.

      Would appreciate your feedback. :)

      It's possible that some bugs may have been introduced... consider this somewhat experimental code.