Example #1
0
def run(args_list):
    global _CurrentProcess
    if _CurrentProcess is not None:
        dhnio.Dprint(4, 'run_upnpc.run WARNING only one process at once')
        return None

    if dhnio.Windows():
        cmdargs = ['upnpc.exe']
    elif dhnio.Linux():
        cmdargs = ['upnpc']
    else:
        return None

    cmdargs += args_list

    if dhnio.Windows():
        # if we run from svn - upnpc.exe is in the p2p folder
        if not os.path.isfile(cmdargs[0]):
            if os.path.isfile(os.path.join('p2p', cmdargs[0])):
                cmdargs[0] = os.path.join('p2p', cmdargs[0])
            else:
                dhnio.Dprint(1, 'run_upnpc.run ERROR can not find executable file ' + cmdargs[0])
                return None

    dhnio.Dprint(6, 'run_upnpc.run is going to execute: %s' % cmdargs)

    try:
        if dhnio.Windows() and dhnio.isFrozen():
            import win32pipe
            _CurrentProcess = win32pipe.popen(subprocess.list2cmdline(cmdargs))
        else:
            _CurrentProcess = nonblocking.Popen(cmdargs, shell=False,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,)
    except OSError:
        dhnio.Dprint(1, 'run_upnpc.run ERROR can not start executable file ' + cmdargs[0])
        return None
    except:
        dhnio.DprintException()
        return None

    try:
        if dhnio.Windows() and dhnio.isFrozen():
            out_data = _CurrentProcess.read()
            returncode = _CurrentProcess.close() or 0
        else:
            out_data = _CurrentProcess.communicate()[0]
            returncode = _CurrentProcess.returncode
    except:
        dhnio.DprintException()
        return None

    dhnio.Dprint(6, 'run_upnpc.run %s finished with return code: %s' % (str(_CurrentProcess), str(returncode)))
    _CurrentProcess = None

    return out_data
Example #2
0
def backuptarfile(filepath, compress=None):
    """
    Almost same - returns file descriptor for process that makes tar archive.
    But tar archive is created from single file, not folder.
    """
    if not os.path.isfile(filepath):
        dhnio.Dprint(1, 'backup_tar.backuptarfile ERROR %s not found' % filepath)
        return None
    if compress is None:
        compress = 'none'
    # dhnio.Dprint(14, "backup_tar.backuptarfile %s compress=%s" % (filepath, compress))
    if dhnio.Windows():
        if dhnio.isFrozen():
            commandpath = "dhnbackup.exe"
            cmdargs = [commandpath, 'nosubdirs', compress, filepath]
        else:
            commandpath = "dhnbackup.py"
            cmdargs = [sys.executable, commandpath, 'nosubdirs', compress, filepath]
    else:
        commandpath = "dhnbackup.py"
        cmdargs = [sys.executable, commandpath, 'nosubdirs', compress, filepath]
    if not os.path.isfile(commandpath):
        dhnio.Dprint(1, 'backup_tar.backuptarfile ERROR %s not found' % commandpath)
        return None
    # dhnio.Dprint(12, "backup_tar.backuptarfile going to execute %s" % str(cmdargs))
    # p = run(cmdargs)
    p = child_process.pipe(cmdargs)
    return p
Example #3
0
def backuptar(directorypath, recursive_subfolders=True, compress=None):
    """
    Returns file descriptor for process that makes tar archive.
    In other words executes a child process and create a Pipe to communicate with it.
    """
    if not os.path.isdir(directorypath):
        dhnio.Dprint(1, 'backup_tar.backuptar ERROR %s not found' % directorypath)
        return None
    subdirs = 'subdirs'
    if not recursive_subfolders:
        subdirs = 'nosubdirs'
    if compress is None:
        compress = 'none'
    # dhnio.Dprint(14, "backup_tar.backuptar %s %s compress=%s" % (directorypath, subdirs, compress))
    if dhnio.Windows():
        if dhnio.isFrozen():
            commandpath = "dhnbackup.exe"
            cmdargs = [commandpath, subdirs, compress, directorypath]
        else:
            commandpath = "dhnbackup.py"
            cmdargs = [sys.executable, commandpath, subdirs, compress, directorypath]
    else:
        commandpath = "dhnbackup.py"
        cmdargs = [sys.executable, commandpath, subdirs, compress, directorypath]
    if not os.path.isfile(commandpath):
        dhnio.Dprint(1, 'backup_tar.backuptar ERROR %s not found' % commandpath)
        return None
    # dhnio.Dprint(14, "backup_tar.backuptar going to execute %s" % str(cmdargs))
    # p = run(cmdargs)
    p = child_process.pipe(cmdargs)
    return p
Example #4
0
def init():
    dhnio.Dprint(4, 'dhnupdate.init')
    update_shedule_file(settings.getUpdatesSheduleData())
    if not dhnio.isFrozen() or not dhnio.Windows():
        dhnio.Dprint(6, 'dhnupdate.init finishing')
        return
    if not os.path.isfile(settings.VersionFile()):
        dhnio.WriteFile(settings.VersionFile(), '')
    SetLocalDir(dhnio.getExecutableDir())
    if settings.getUpdatesMode() != settings.getUpdatesModeValues()[2]:
        dhnio.Dprint(6, 'dhnupdate.init starting the loop')
        reactor.callLater(0, loop, True)
    else:
        dhnio.Dprint(6, 'dhnupdate.init skip, update mode is: %s' % settings.getUpdatesMode())
Example #5
0
def run(Tester):
    global _CurrentProcess
    # dhnio.Dprint(8, 'localtester.run ' + str(Tester))

    if dhnio.isFrozen() and dhnio.Windows():
        commandpath = "dhntester.exe"
        cmdargs = [commandpath, Tester]
    else:
        commandpath = "dhntester.py"
        cmdargs = [sys.executable, commandpath, Tester]

    if not os.path.isfile(commandpath):
        dhnio.Dprint(1, "localtester.run ERROR %s not found" % commandpath)
        return None

    dhnio.Dprint(14, "localtester.run execute: %s" % cmdargs)

    try:
        if dhnio.Windows():
            import win32process

            _CurrentProcess = nonblocking.Popen(
                cmdargs,
                shell=False,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=False,
                creationflags=win32process.CREATE_NO_WINDOW,
            )
        else:
            _CurrentProcess = nonblocking.Popen(
                cmdargs,
                shell=False,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                universal_newlines=False,
            )
    except:
        dhnio.Dprint(1, "localtester.run ERROR executing: %s" % str(cmdargs))
        dhnio.DprintException()
        return None
    return _CurrentProcess
Example #6
0
def extracttar(tarfile, outdir):
    """
    Opposite method, run dhnbackup to extract files and folders from ".tar" file.
    """
    if not os.path.isfile(tarfile):
        dhnio.Dprint(1, 'backup_tar.extracttar ERROR %s not found' % tarfile)
        return None
    # dhnio.Dprint(12, "backup_tar.extracttar %s %s" % (tarfile, outdir))
    if dhnio.Windows():
        if dhnio.isFrozen():
            commandpath = 'dhnbackup.exe'
            cmdargs = [commandpath, 'extract', tarfile, outdir]
        else:
            commandpath = "dhnbackup.py"
            cmdargs = [sys.executable, commandpath, 'extract', tarfile, outdir]
    else:
        commandpath = "dhnbackup.py"
        cmdargs = [sys.executable, commandpath, 'extract', tarfile, outdir]
    if not os.path.isfile(commandpath):
        dhnio.Dprint(1, 'backup_tar.extracttar ERROR %s is not found' % commandpath)
        return None
    # p = run(cmdargs)
    p = child_process.pipe(cmdargs)
    return p
Example #7
0
def cmd_uninstall(opts, args, overDict):
    if not dhnio.Windows():
        print 'This command can be used only under OS Windows.'
        return 0
    if not dhnio.isFrozen():
        print 'You are running DataHaven.NET from sources, uninstall command is available only for binary version.'
        return 0
    def do_uninstall():
        dhnio.Dprint(0, 'command_line.do_uninstall')
        # batfilename = misc.MakeBatFileToUninstall()
        # misc.UpdateRegistryUninstall(True)
        # misc.RunBatFile(batfilename, 'c:/out2.txt')
    def kill():
        dhnio.Dprint(0, 'kill')
        total_count = 0
        found = False
        while True:
            appList = dhnio.find_process([
                'dhnmain.exe',
                'dhnmain.py',
                'dhn.py',
                'regexp:^/usr/bin/python\ +/usr/bin/datahaven.*$',
                'dhnview.exe',
                'dhnview.py',
                'dhnbackup.exe',
                'dhnbackup.py',
                'dhntester.exe',
                'dhntester.py',
                'dhnstarter.exe',
                ])
            if len(appList) > 0:
                found = True
            for pid in appList:
                dhnio.Dprint(0, 'trying to stop pid %d' % pid)
                dhnio.kill_process(pid)
            if len(appList) == 0:
                if found:
                    dhnio.Dprint(0, 'DataHaven.NET stopped\n')
                else:
                    dhnio.Dprint(0, 'DataHaven.NET was not started\n')
                return 0
            total_count += 1
            if total_count > 10:
                dhnio.Dprint(0, 'some DataHaven.NET process found, but can not stop it\n')
                return 1
            time.sleep(1)            
    def wait_then_kill(x):
        dhnio.Dprint(0, 'wait_then_kill')
        total_count = 0
        #while True:
        def _try():
            dhnio.Dprint(0, '_try')
            appList = dhnio.find_process([
                'dhnmain.exe',
                'dhnview.exe',
                'dhnbackup.exe',
                'dhntester.exe',
                'dhnstarter.exe',
                ])
            dhnio.Dprint(0, 'appList:' + str(appList))
            if len(appList) == 0:
                dhnio.Dprint(0, 'finished')
                reactor.stop()
                do_uninstall()
                return 0
            total_count += 1
            dhnio.Dprint(0, '%d' % total_count)
            if total_count > 10:
                dhnio.Dprint(0, 'not responding')
                ret = kill()
                reactor.stop()
                if ret == 0:
                    do_uninstall()
                return ret
            reactor.callLater(1, _try)
        _try()
#            time.sleep(1)
    appList = dhnio.find_process([
        'dhnmain.exe',
        'dhnview.exe',
        'dhnbackup.exe',
        'dhntester.exe',
        'dhnstarter.exe',
        ])
    if len(appList) == 0:
        dhnio.Dprint(0, 'uninstalling DataHaven.NET ...   ')
        do_uninstall()
        return 0
    dhnio.Dprint(0, 'found DataHaven.NET processes ...   ')
    try:
        url = webcontrol._PAGE_ROOT+'?action=exit'
        run_url_command(url).addCallback(wait_then_kill)
        #reactor.addSystemEventTrigger('before', 'shutdown', do_uninstall)
        reactor.run()
        return 0
    except:
        dhnio.DprintException()
        ret = kill()
        if ret == 0:
            do_uninstall()
        return ret
Example #8
0
def main():
    """
    THIS IS THE ENTRY POINT OF THE PROGRAM!
    """
    try:
        import lib.dhnio as dhnio
    except:
        dirpath = os.path.dirname(os.path.abspath(sys.argv[0]))
        sys.path.insert(0, os.path.abspath('datahaven'))
        sys.path.insert(0, os.path.abspath(os.path.join(dirpath, '..')))
        sys.path.insert(0, os.path.abspath(os.path.join(dirpath, '..', '..')))
        try:
            import lib.dhnio as dhnio
        except:
            return 1

    # init IO module, update locale
    dhnio.init()

    # TODO
    # sys.excepthook = dhnio.ExceptionHook
    if not dhnio.isFrozen():
        from twisted.internet.defer import setDebugging
        setDebugging(True)

    # ask dhnio to count time for each line from that moment, not absolute time 
    dhnio.LifeBegins()

    pars = parser()
    (opts, args) = pars.parse_args()

    if opts.no_logs:
        dhnio.DisableLogs()

    #---logpath---
    logpath = ''
    if dhnio.Windows():
        logpath = os.path.join(os.environ['APPDATA'], 'DataHaven.NET', 'logs', 'dhnmainstart.log')
    elif dhnio.Linux():
        old_path = os.path.join(os.path.expanduser('~'), 'datahavennet')
        if os.path.isdir(old_path):
            logpath = os.path.join(old_path, 'logs', 'dhnmainstart.log')
        else:
            logpath = os.path.join(os.path.expanduser('~'), '.datahaven', 'logs', 'dhnmainstart.log')

    if opts.output:
        logpath = opts.output

    if logpath != '':
        dhnio.OpenLogFile(logpath)
        dhnio.Dprint(2, 'dhnmain.main log file opened ' + logpath)
        if dhnio.Windows() and dhnio.isFrozen():
            dhnio.StdOutRedirectingStart()
            dhnio.Dprint(2, 'dhnmain.main redirecting started')

    if opts.debug or str(opts.debug) == '0':
        dhnio.SetDebug(opts.debug)

    if opts.quite and not opts.verbose:
        dhnio.DisableOutput()

    if opts.verbose:
        copyright()

    dhnio.Dprint(2, 'dhnmain.main started ' + time.asctime())

    overDict = override_options(opts, args)

    cmd = ''
    if len(args) > 0:
        cmd = args[0].lower()
        
    dhnio.Dprint(2, 'dhnmain.main args=%s' % str(args))

    #---start---
    if cmd == '' or cmd == 'start' or cmd == 'go':
        appList = dhnio.find_process([
            'dhnmain.exe',
            'dhnmain.py',
            'dhn.py',
            'regexp:^/usr/bin/python\ +/usr/bin/datahaven.*$',
            ])
        
#        pid = -1
#        try:
#            if dhnio.Windows():
#                dhn_data_path = os.path.join(os.environ.get('APPDATA', os.path.join(os.path.expanduser('~'), 'Application Data')), 'DataHaven.NET')
#                pid_path = os.path.join(dhn_data_path, 'metadata', 'processid')
#            else:
#                pid_path = os.path.join(os.path.expanduser('~'), '.datahaven', 'metadata', 'processid')
#            if os.path.isfile(pid_path):
#                pid = int(dhnio.ReadBinaryFile(pid_path).strip())
#        except:
#            dhnio.DprintException()
        # this is extra protection for Debian release
        # I am nut sure how process name can looks on different systems
        # check the process ID from previous start 
        # it file exists and we found this PID in the currently running apps - DHN is working
        # if file not exists we don't want to start if found some other jobs with same name 
        # PREPRO probably in future we can switch to this line:
        # if len(appList) > 0 and pid != -1 and pid in appList
        # because if we do not have pid - the process is not working
        # but old versions do not have pid file so we need to wait till 
        # all users be updated to this version - revision 7520+
#        if len(appList) > 0 and ( ( pid != -1 and pid in appList ) or ( pid == -1 ) ):

        if len(appList) > 0:
            dhnio.Dprint(0, 'DataHaven.NET already started, found another process: %s' % str(appList))
            dhnio.shutdown()
            return 0
        ret = run('', opts, args, overDict)
        dhnio.shutdown()
        return ret

    #---restart---
    elif cmd == 'restart':
        appList = dhnio.find_process([
            'dhnmain.exe',
            'dhnmain.py',
            'dhn.py',
            'regexp:^/usr/bin/python\ +/usr/bin/datahaven.*$',
            ])
        if len(appList) > 0:
            dhnio.Dprint(0, 'found main DataHaven.NET process: %s, sending "restart" command ... ' % str(appList), '')
            def done(x):
                dhnio.Dprint(0, 'DONE\n', '')
                from twisted.internet import reactor
                if reactor.running and not reactor._stopped:
                    reactor.stop()
            def failed(x):
                dhnio.Dprint(0, 'FAILED, killing previous process and do restart\n', '')
                try:
                    kill()
                except:
                    dhnio.DprintException()
                from twisted.internet import reactor
                import lib.misc as misc
                reactor.addSystemEventTrigger('after','shutdown', misc.DoRestart)
                reactor.stop()
            try:
                from twisted.internet import reactor
                from command_line import run_url_command
                d = run_url_command('?action=restart', False)
                d.addCallback(done)
                d.addErrback(failed)
                reactor.run()
                dhnio.shutdown()
                return 0
            except:
                dhnio.DprintException()
                dhnio.shutdown()
                return 1
        else:
            ret = run('', opts, args, overDict)
            dhnio.shutdown()
            return ret

    #---show---
    elif cmd == 'show' or cmd == 'open':
        appList_dhnview = dhnio.find_process([
            'dhnview.exe',
            'dhnview.py',
            ])
        appList = dhnio.find_process([
            'dhnmain.exe',
            'dhnmain.py',
            'dhn.py',
            'regexp:^/usr/bin/python\ +/usr/bin/datahaven.*$',
            ])
        if len(appList_dhnview) > 0:
            if len(appList) == 0:
                for pid in appList_dhnview:
                    dhnio.kill_process(pid)
            else:
                dhnio.Dprint(0, 'DataHaven.NET GUI already opened, found another process: %s' % str(appList))
                dhnio.shutdown()
                return 0
        if len(appList) == 0:
            ret = run('show', opts, args, overDict)
            dhnio.shutdown()
            return ret
        
        dhnio.Dprint(0, 'found main DataHaven.NET process: %s, start the GUI\n' % str(appList))
        ret = show()
        dhnio.shutdown()
        return ret

    #---stop---
    elif cmd == 'stop' or cmd == 'kill' or cmd == 'shutdown':
        appList = dhnio.find_process([
            'dhnmain.exe',
            'dhnmain.py',
            'dhn.py',
            'regexp:^/usr/bin/python\ +/usr/bin/datahaven.*$',
            ])
        if len(appList) > 0:
            dhnio.Dprint(0, 'found main DataHaven.NET process: %s, sending command "exit" ... ' % str(appList), '')
            try:
                from twisted.internet import reactor
                from command_line import run_url_command
                url = '?action=exit'
                run_url_command(url, False).addBoth(wait_then_kill)
                reactor.run()
                dhnio.shutdown()
                return 0
            except:
                dhnio.DprintException()
                ret = kill()
                dhnio.shutdown()
                return ret
        else:
            dhnio.Dprint(0, 'DataHaven.NET is not running at the moment')
            dhnio.shutdown()
            return 0

    #---uninstall---
    elif cmd == 'uninstall':
        def do_spawn(x=None):
            from lib.settings import WindowsStarterFileName
            starter_filepath = os.path.join(dhnio.getExecutableDir(), WindowsStarterFileName())
            dhnio.Dprint(0, "dhnmain.main dhnstarter.exe path: %s " % starter_filepath)
            if not os.path.isfile(starter_filepath):
                dhnio.Dprint(0, "dhnmain.main ERROR %s not found" % starter_filepath)
                dhnio.shutdown()
                return 1
            cmdargs = [os.path.basename(starter_filepath), 'uninstall']
            dhnio.Dprint(0, "dhnmain.main os.spawnve cmdargs="+str(cmdargs))
            ret = os.spawnve(os.P_DETACH, starter_filepath, cmdargs, os.environ)
            dhnio.shutdown()
            return ret
        def do_reactor_stop_and_spawn(x=None):
            reactor.stop()
            ret = do_spawn()
            dhnio.shutdown()
            return ret
        dhnio.Dprint(0, 'dhnmain.main UNINSTALL!')
        if not dhnio.Windows():
            dhnio.Dprint(0, 'This command can be used only under OS Windows.')
            dhnio.shutdown()
            return 0
        if not dhnio.isFrozen():
            dhnio.Dprint(0, 'You are running DataHaven.NET from sources, uninstall command is available only for binary version.')
            dhnio.shutdown()
            return 0
        appList = dhnio.find_process(['dhnmain.exe',])
        if len(appList) > 0:
            dhnio.Dprint(0, 'found main DataHaven.NET process...   ', '')
            try:
                from twisted.internet import reactor
                from command_line import run_url_command
                url = '?action=exit'
                run_url_command(url).addBoth(do_reactor_stop_and_spawn)
                reactor.run()
                dhnio.shutdown()
                return 0
            except:
                dhnio.DprintException()
        ret = do_spawn()
        dhnio.shutdown()
        return ret
        
    #---command_line---
    import command_line
    ret = command_line.run(opts, args, overDict, pars)
    if ret == 2:
        print usage()
    dhnio.shutdown()
    return ret 
Example #9
0
def run(UI='', options=None, args=None, overDict=None):
    """
    In the method `main()` program firstly checks the command line arguments 
    and then calls this method to start the whole process.
    This initialize some low level modules and finally create 
    an instance of `initializer()` state machine and send it an event "run".
    """
    
    import lib.dhnio as dhnio
    dhnio.Dprint(6, 'dhnmain.run sys.path=%s' % str(sys.path))
    
    #---USE_TRAY_ICON---
    try:
        from dhnicon import USE_TRAY_ICON
        dhnio.Dprint(4, 'dhnmain.run USE_TRAY_ICON='+str(USE_TRAY_ICON))
        if dhnio.Linux() and not dhnio.X11_is_running():
            USE_TRAY_ICON = False
        if USE_TRAY_ICON:
            from twisted.internet import wxreactor
            wxreactor.install()
    except:
        USE_TRAY_ICON = False
        dhnio.DprintException()

    if USE_TRAY_ICON:
        if dhnio.Linux():
            icons_dict = {
                'red':      'icon-red-24x24.png',
                'green':    'icon-green-24x24.png',
                'gray':     'icon-gray-24x24.png',
                }
        else:
            icons_dict = {
                'red':      'icon-red.png',
                'green':    'icon-green.png',
                'gray':     'icon-gray.png',
                }
        import dhnicon
        icons_path = str(os.path.abspath(os.path.join(dhnio.getExecutableDir(), 'icons')))
        dhnio.Dprint(4, 'dhnmain.run call dhnicon.init(%s)' % icons_path)
        dhnicon.init(icons_path, icons_dict)
        def _tray_control_func(cmd):
            if cmd == 'exit':
                #import dhninit
                #dhninit.shutdown_exit()
                import shutdowner
                shutdowner.A('stop', 'exit')
        dhnicon.SetControlFunc(_tray_control_func)

    dhnio.Dprint(4, 'dhnmain.run want to import twisted.internet.reactor')
    try:
        from twisted.internet import reactor
    except:
        dhnio.DprintException()
        sys.exit('Error initializing reactor in dhnmain.py\n')

    #---settings---
    import lib.settings as settings
    if overDict:
        settings.override_dict(overDict)
    settings.init()
    if not options or options.debug is None:
        dhnio.SetDebug(settings.getDebugLevel())

    #---logfile----
    if dhnio.EnableLog and dhnio.LogFile is not None:
        dhnio.Dprint(2, 'dhnmain.run want to switch log files')
        if dhnio.Windows() and dhnio.isFrozen():
            dhnio.StdOutRedirectingStop()
        dhnio.CloseLogFile()
        dhnio.OpenLogFile(settings.MainLogFilename()+'-'+time.strftime('%y%m%d%H%M%S')+'.log')
        if dhnio.Windows() and dhnio.isFrozen():
            dhnio.StdOutRedirectingStart()
            
    #---memdebug---
    if settings.uconfig('logs.memdebug-enable') == 'True':
        try:
            import lib.memdebug as memdebug
            memdebug_port = int(settings.uconfig('logs.memdebug-port'))
            memdebug.start(memdebug_port)
            reactor.addSystemEventTrigger('before', 'shutdown', memdebug.stop)
            dhnio.Dprint(2, 'dhnmain.run memdebug web server started on port %d' % memdebug_port)
        except:
            dhnio.DprintException()  
            
    #---process ID---
    try:
        pid = os.getpid()
        pid_file_path = os.path.join(settings.MetaDataDir(), 'processid')
        dhnio.WriteFile(pid_file_path, str(pid))
        dhnio.Dprint(2, 'dhnmain.run wrote process id [%s] in the file %s' % (str(pid), pid_file_path))
    except:
        dhnio.DprintException()  
            
#    #---reactor.callLater patch---
#    if dhnio.Debug(12):
#        patchReactorCallLater(reactor)
#        monitorDelayedCalls(reactor)

    dhnio.Dprint(2,"dhnmain.run UI=[%s]" % UI)

    if dhnio.Debug(10):
        dhnio.Dprint(0, '\n' + dhnio.osinfofull())

    dhnio.Dprint(4, 'dhnmain.run import automats')

    #---START!---
    import lib.automat as automat
    automat.LifeBegins(dhnio.LifeBeginsTime)
    automat.OpenLogFile(settings.AutomatsLog())
    
    import initializer
    import shutdowner

    dhnio.Dprint(4, 'dhnmain.run send event "run" to initializer()')
    
    #reactor.callLater(0, initializer.A, 'run', UI)
    initializer.A('run', UI)

    #reactor.addSystemEventTrigger('before', 'shutdown', lambda : initializer.A('reactor-stopped'))

    dhnio.Dprint(2, 'dhnmain.run calling reactor.run()')
    reactor.run()
    dhnio.Dprint(2, 'dhnmain.run reactor stopped')
    # this will call initializer() without reactor.callLater(0, ... )
    # we do not have any timers initializer() so do not worry
    #initializer.A('reactor-stopped', use_reactor = False)
    shutdowner.A('reactor-stopped')

    dhnio.Dprint(2, 'dhnmain.run finished, EXIT')

    automat.objects().clear()
    automat.CloseLogFile()

##    import threading
##    dhnio.Dprint(0, 'threads:')
##    for t in threading.enumerate():
##        dhnio.Dprint(0, '  '+str(t))

    dhnio.CloseLogFile()

    if dhnio.Windows() and dhnio.isFrozen():
        dhnio.StdOutRedirectingStop()

    return 0