<div><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">Hello everyone! I wrote Twisted-based TCP server which is capable of running in several relatively different modes. When mode switch is needed, I would like the server to restart itself by some means, for it to read new mode from configuration file and create corresponding implementation. Also I wanted the restart to occur without re-running twistd process, because it seems to me more appropriate for Linux daemon.</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">So I organized code in the .tac file in the following way:</span></strong></p> <p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;"># imports...</span></strong></p> <p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">CONFIG_FILE_NAME = "master.conf"</span></strong></p> <p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">def main():</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   print("Entered main")</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   config = ConfigParser.RawConfigParser()</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   config.read(CONFIG_FILE_NAME)</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   context = MasterPlayerImplementationContext()</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   context.config_file_name = CONFIG_FILE_NAME</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   context.reactor = reactor</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   print("Creating internet.TCPServer...")</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   master_player_service = internet.TCPServer(config.getint(shared_types.CONFIG_SECTION_GENERAL,</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">                                    shared_types.CONFIG_PARAMETER_SERVER_PORT),</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">                      pb.PBServerFactory(MasterPlayer(context)),</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">                      50, config.get(shared_types.CONFIG_SECTION_GENERAL,</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">                                     shared_types.CONFIG_PARAMETER_SERVER_IP))</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   def stop_service_succeeded(arg):</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       print("Service stop succeeded! arg is {}. Restarting...".format(arg))</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       main()</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   def stop_service_failed(failure):</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       print("Service stop failed! failure is {}. Trying to restart nevertheless...".format(failure))</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       main()</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   def restart_callback():</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       print("Entered restart_callback")</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       deferred = defer.maybeDeferred(master_player_service.disownServiceParent)</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       deferred.addCallback(stop_service_succeeded).addErrback(stop_service_failed)</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">       print("Leaving restart_callback")</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   context.restart_callback = restart_callback</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   master_player_service.setServiceParent(service_collection)</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">   print("Exiting main")</span></strong></p> <p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">application = service.Application("master_player")</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">service_collection = service.IServiceCollection(application)</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">main()</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">print("After main")</span></strong></p> <p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">When the server is in need of restarting itself, it just calls the context.restart_callback function and restart occurs immediately.</span></strong></p><p style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">My experience in Linux, Python and Twisted is rather modest, so I would like to consult here to determine whether solution chosen is the right one. </span></strong></p><br /><strong style="font-weight:normal;"><span style="background-color:transparent;color:#000000;font-family:arial;font-size:11pt;font-style:normal;font-variant:normal;font-weight:400;text-decoration:none;vertical-align:baseline;white-space:pre-wrap;">P.S. The second aim, in case the solution is not very bad or in case there will be better solution pointed out, is to leave answer to the “How to restart Twisted service” question in this mailing list, because it took me relatively large amount of time for searching through old mailing list entries and StackOverflow questions.</span></strong></div><div> </div><div>-- </div><div>Kind regards, Roman Mescheryakov</div><div> </div>