def iterate(parent_pid,elementDescript,paramsDescript,signatureDescript,x509_proxy_plugin):
    sleep_time=int(elementDescript.frontend_data['LoopDelay'])
    
    factory_pools=elementDescript.merged_data['FactoryCollectors']

    frontend_name=elementDescript.frontend_data['FrontendName']
    group_name=elementDescript.element_data['GroupName']

    stats={}
    history_obj={}

    if not elementDescript.frontend_data.has_key('X509Proxy'):
        published_frontend_name='%s.%s'%(frontend_name,group_name)
    else:
        # if using a VO proxy, label it as such
        # this way we don't risk of using the wrong proxy on the other side
        # if/when we decide to stop using the proxy
        published_frontend_name='%s.XPVO_%s'%(frontend_name,group_name)

    try:
        is_first=1
        while 1: # will exit by exception
            check_parent(parent_pid)
            glideinFrontendLib.log_files.logActivity("Iteration at %s" % time.ctime())
            try:
                # recreate every time (an easy way to start from a clean state)
                stats['group']=glideinFrontendMonitoring.groupStats()
                
                done_something=iterate_one(published_frontend_name,elementDescript,paramsDescript,signatureDescript,x509_proxy_plugin,stats,history_obj)
                
                glideinFrontendLib.log_files.logActivity("Writing stats")
                try:
                    write_stats(stats)
                except KeyboardInterrupt:
                    raise # this is an exit signal, pass through
                except:
                    # never fail for stats reasons!
                    tb = traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
                                                    sys.exc_info()[2])
                    glideinFrontendLib.log_files.logWarning("Unhandled exception, ignoring. See debug log for more details.")
                    glideinFrontendLib.log_files.logDebug("Exception occurred: %s" % tb)
            except KeyboardInterrupt:
                raise # this is an exit signal, pass trough
            except:
                if is_first:
                    raise
                else:
                    # if not the first pass, just warn
                    tb = traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],
                                                    sys.exc_info()[2])
                    glideinFrontendLib.log_files.logWarning("Unhandled exception, ignoring. See debug log for more details.")
                    glideinFrontendLib.log_files.logDebug("Exception occurred: %s" % tb)
            is_first=0
            
            # do it just before the sleep
            glideinFrontendLib.log_files.cleanup()

            glideinFrontendLib.log_files.logActivity("Sleep")
            time.sleep(sleep_time)
    finally:
        glideinFrontendLib.log_files.logActivity("Deadvertize my ads")
        for factory_pool in factory_pools:
            factory_pool_node=factory_pool[0]
            try:
                glideinFrontendInterface.deadvertizeAllWork(factory_pool_node,published_frontend_name)
            except:
                pass # just ignore errors... this was cleanup

        # Invalidate all resource classads
        try:
            resource_advertiser = glideinFrontendInterface.ResourceClassadAdvertiser()
            resource_advertiser.invalidateConstrainedClassads('GlideClientName == "%s"' % published_frontend_name)
        except:
            # Ignore all errors
            pass
                                                    sys.exc_info()[2])
                    logSupport.log.warning("Unhandled exception, ignoring. See debug log for more details.")
                    logSupport.log.debug("Exception occurred: %s" % tb)
            is_first = 0

            # do it just before the sleep
            cleanupSupport.cleaners.cleanup()

            logSupport.log.info("Sleep")
            time.sleep(sleep_time)
    finally:
        logSupport.log.info("Deadvertize my ads")
        for factory_pool in factory_pools:
            factory_pool_node = factory_pool[0]
            try:
                glideinFrontendInterface.deadvertizeAllWork(factory_pool_node, published_frontend_name)
            except:
                pass # just ignore errors... this was cleanup

        # Invalidate all resource classads
        try:
            resource_advertiser = glideinFrontendInterface.ResourceClassadAdvertiser()
            resource_advertiser.invalidateConstrainedClassads('GlideClientName == "%s"' % published_frontend_name)
        except:
            # Ignore all errors
            pass
            

############################################################
def main(parent_pid, work_dir, group_name):
    startup_time = time.time()