We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Running with --nodaemon and PID files
This ticket is a migrated Trac ticket [3608](http://trac.buildbot.net/ticket/3608)

People contributed to the original ticket: @unknown_contributor
Ticket created on: `Sep 12 2016`
Ticket last modified on: `Sep 12 2016`

---

Both the master and the worker still use PID files while running with --nodaemon. I've had issues with workers running with --nodaemon not starting because of an old, stale PID file, corresponding to an actual process belonging to another user.

This can be thought to be inconsistent, and harms the writing ofreally simple non forking configuration files to manage the process through an external service manager (systemd, supervisord etc.).

It seems that the cousin ``twistd`` executable has a --pidfile argument, that can be used to mean "no pid file". This is explained notably in https://twistedmatrix.com/documents/current/core/howto/systemd.html.

We could expose that, or we could decide that --nodaemon implies no pid file.

I believe this is true in Eight and Nine, and that a fix could be easily backported
(marking this as minor, because it's easy to circumvent by putting appropriate rms in unit files or other confs)


---




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `worker/buildbot_worker/scripts/start.py`
Content:
```
1 # This file is part of Buildbot.  Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 
16 from __future__ import absolute_import
17 from __future__ import division
18 from __future__ import print_function
19 
20 import os
21 import sys
22 import time
23 
24 from buildbot_worker.scripts import base
25 from buildbot_worker.util import rewrap
26 
27 
28 class Follower(object):
29 
30     def follow(self):
31         from twisted.internet import reactor
32         from buildbot_worker.scripts.logwatcher import LogWatcher
33         self.rc = 0
34         print("Following twistd.log until startup finished..")
35         lw = LogWatcher("twistd.log")
36         d = lw.start()
37         d.addCallbacks(self._success, self._failure)
38         reactor.run()
39         return self.rc
40 
41     def _success(self, processtype):
42         from twisted.internet import reactor
43         print("The %s appears to have (re)started correctly." % processtype)
44         self.rc = 0
45         reactor.stop()
46 
47     def _failure(self, why):
48         from twisted.internet import reactor
49         from buildbot_worker.scripts.logwatcher import WorkerTimeoutError
50         if why.check(WorkerTimeoutError):
51             print(rewrap("""\
52                 The worker took more than 10 seconds to start and/or connect
53                 to the buildmaster, so we were unable to confirm that it
54                 started and connected correctly.
55                 Please 'tail twistd.log' and look for a line that says
56                 'message from master: attached' to verify correct startup.
57                 If you see a bunch of messages like 'will retry in 6 seconds',
58                 your worker might not have the correct hostname or portnumber
59                 for the buildmaster, or the buildmaster might not be running.
60                 If you see messages like
61                    'Failure: twisted.cred.error.UnauthorizedLogin'
62                 then your worker might be using the wrong botname or password.
63                 Please correct these problems and then restart the worker.
64                 """))
65         else:
66             print(rewrap("""\
67                 Unable to confirm that the worker started correctly.
68                 You may need to stop it, fix the config file, and restart.
69                 """))
70             print(why)
71         self.rc = 1
72         reactor.stop()
73 
74 
75 def startCommand(config):
76     basedir = config['basedir']
77     if not base.isWorkerDir(basedir):
78         return 1
79 
80     return startWorker(basedir, config['quiet'], config['nodaemon'])
81 
82 
83 def startWorker(basedir, quiet, nodaemon):
84     """
85     Start worker process.
86 
87     Fork and start twisted application described in basedir buildbot.tac file.
88     Print it's log messages to stdout for a while and try to figure out if
89     start was successful.
90 
91     If quiet or nodaemon parameters are True, or we are running on a win32
92     system, will not fork and log will not be printed to stdout.
93 
94     @param  basedir: worker's basedir path
95     @param    quiet: don't display startup log messages
96     @param nodaemon: don't daemonize (stay in foreground)
97     @return: 0 if worker was successfully started,
98              1 if we are not sure that worker started successfully
99     """
100 
101     os.chdir(basedir)
102     if quiet or nodaemon:
103         return launch(nodaemon)
104 
105     # we probably can't do this os.fork under windows
106     from twisted.python.runtime import platformType
107     if platformType == "win32":
108         return launch(nodaemon)
109 
110     # fork a child to launch the daemon, while the parent process tails the
111     # logfile
112     if os.fork():
113         # this is the parent
114         rc = Follower().follow()
115         return rc
116     # this is the child: give the logfile-watching parent a chance to start
117     # watching it before we start the daemon
118     time.sleep(0.2)
119     launch(nodaemon)
120 
121 
122 def launch(nodaemon):
123     sys.path.insert(0, os.path.abspath(os.getcwd()))
124 
125     # see if we can launch the application without actually having to
126     # spawn twistd, since spawning processes correctly is a real hassle
127     # on windows.
128     from twisted.python.runtime import platformType
129     argv = ["twistd",
130             "--no_save",
131             "--logfile=twistd.log",  # windows doesn't use the same default
132             "--python=buildbot.tac"]
133     if nodaemon:
134         argv.extend(['--nodaemon'])
135     sys.argv = argv
136 
137     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
138     # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for
139     # windows.
140     from twisted import __version__
141     major, minor, ignored = __version__.split(".", 2)
142     major = int(major)
143     minor = int(minor)
144     if (platformType == "win32" and (major == 2 and minor < 5)):
145         from twisted.scripts import _twistw
146         run = _twistw.run
147     else:
148         from twisted.scripts import twistd
149         run = twistd.run
150     run()
151
```

Path: `master/buildbot/scripts/start.py`
Content:
```
1 # This file is part of Buildbot.  Buildbot is free software: you can
2 # redistribute it and/or modify it under the terms of the GNU General Public
3 # License as published by the Free Software Foundation, version 2.
4 #
5 # This program is distributed in the hope that it will be useful, but WITHOUT
6 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
7 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
8 # details.
9 #
10 # You should have received a copy of the GNU General Public License along with
11 # this program; if not, write to the Free Software Foundation, Inc., 51
12 # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
13 #
14 # Copyright Buildbot Team Members
15 
16 from __future__ import absolute_import
17 from __future__ import division
18 from __future__ import print_function
19 
20 import os
21 import sys
22 
23 from twisted.internet import protocol
24 from twisted.internet import reactor
25 from twisted.python.runtime import platformType
26 
27 from buildbot.scripts import base
28 from buildbot.scripts.logwatcher import BuildmasterStartupError
29 from buildbot.scripts.logwatcher import BuildmasterTimeoutError
30 from buildbot.scripts.logwatcher import LogWatcher
31 from buildbot.scripts.logwatcher import ReconfigError
32 from buildbot.util import rewrap
33 
34 
35 class Follower:
36 
37     def follow(self, basedir):
38         self.rc = 0
39         print("Following twistd.log until startup finished..")
40         lw = LogWatcher(os.path.join(basedir, "twistd.log"))
41         d = lw.start()
42         d.addCallbacks(self._success, self._failure)
43         reactor.run()
44         return self.rc
45 
46     def _success(self, _):
47         print("The buildmaster appears to have (re)started correctly.")
48         self.rc = 0
49         reactor.stop()
50 
51     def _failure(self, why):
52         if why.check(BuildmasterTimeoutError):
53             print(rewrap("""\
54                 The buildmaster took more than 10 seconds to start, so we were
55                 unable to confirm that it started correctly.
56                 Please 'tail twistd.log' and look for a line that says
57                 'BuildMaster is running' to verify correct startup.
58                 """))
59         elif why.check(ReconfigError):
60             print(rewrap("""\
61                 The buildmaster appears to have encountered an error in the
62                 master.cfg config file during startup.
63                 Please inspect and fix master.cfg, then restart the
64                 buildmaster.
65                 """))
66         elif why.check(BuildmasterStartupError):
67             print(rewrap("""\
68                 The buildmaster startup failed. Please see 'twistd.log' for
69                 possible reason.
70                 """))
71         else:
72             print(rewrap("""\
73                 Unable to confirm that the buildmaster started correctly.
74                 You may need to stop it, fix the config file, and restart.
75                 """))
76             print(why)
77         self.rc = 1
78         reactor.stop()
79 
80 
81 def launchNoDaemon(config):
82     os.chdir(config['basedir'])
83     sys.path.insert(0, os.path.abspath(config['basedir']))
84 
85     argv = ["twistd",
86             "--no_save",
87             '--nodaemon',
88             "--logfile=twistd.log",  # windows doesn't use the same default
89             "--python=buildbot.tac"]
90     sys.argv = argv
91 
92     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
93     # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for
94     # windows.
95     from twisted.scripts import twistd
96     twistd.run()
97 
98 
99 def launch(config):
100     os.chdir(config['basedir'])
101     sys.path.insert(0, os.path.abspath(config['basedir']))
102 
103     # see if we can launch the application without actually having to
104     # spawn twistd, since spawning processes correctly is a real hassle
105     # on windows.
106     argv = [sys.executable,
107             "-c",
108             # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
109             # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for
110             # windows.
111             "from twisted.scripts import twistd; twistd.run()",
112             "--no_save",
113             "--logfile=twistd.log",  # windows doesn't use the same default
114             "--python=buildbot.tac"]
115 
116     # ProcessProtocol just ignores all output
117     proc = reactor.spawnProcess(
118         protocol.ProcessProtocol(), sys.executable, argv, env=os.environ)
119 
120     if platformType == "win32":
121         with open("twistd.pid", "w") as pidfile:
122             pidfile.write("{0}".format(proc.pid))
123 
124 
125 def start(config):
126     if not base.isBuildmasterDir(config['basedir']):
127         return 1
128 
129     if config['nodaemon']:
130         launchNoDaemon(config)
131         return 0
132 
133     launch(config)
134 
135     # We don't have tail on windows
136     if platformType == "win32" or config['quiet']:
137         return 0
138 
139     # this is the parent
140     rc = Follower().follow(config['basedir'])
141     return rc
142
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/master/buildbot/scripts/start.py b/master/buildbot/scripts/start.py
--- a/master/buildbot/scripts/start.py
+++ b/master/buildbot/scripts/start.py
@@ -84,9 +84,14 @@
 
     argv = ["twistd",
             "--no_save",
-            '--nodaemon',
+            "--nodaemon",
             "--logfile=twistd.log",  # windows doesn't use the same default
             "--python=buildbot.tac"]
+
+    if platformType != 'win32':
+        # windows doesn't use pidfile option.
+        argv.extend(["--pidfile="])
+
     sys.argv = argv
 
     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use
diff --git a/worker/buildbot_worker/scripts/start.py b/worker/buildbot_worker/scripts/start.py
--- a/worker/buildbot_worker/scripts/start.py
+++ b/worker/buildbot_worker/scripts/start.py
@@ -131,7 +131,11 @@
             "--logfile=twistd.log",  # windows doesn't use the same default
             "--python=buildbot.tac"]
     if nodaemon:
-        argv.extend(['--nodaemon'])
+        argv.extend(["--nodaemon"])
+        if platformType != 'win32':
+            # windows doesn't use pidfile option.
+            argv.extend(["--pidfile="])
+
     sys.argv = argv
 
     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use

{"golden_diff": "diff --git a/master/buildbot/scripts/start.py b/master/buildbot/scripts/start.py\n--- a/master/buildbot/scripts/start.py\n+++ b/master/buildbot/scripts/start.py\n@@ -84,9 +84,14 @@\n \n     argv = [\"twistd\",\n             \"--no_save\",\n-            '--nodaemon',\n+            \"--nodaemon\",\n             \"--logfile=twistd.log\",  # windows doesn't use the same default\n             \"--python=buildbot.tac\"]\n+\n+    if platformType != 'win32':\n+        # windows doesn't use pidfile option.\n+        argv.extend([\"--pidfile=\"])\n+\n     sys.argv = argv\n \n     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\ndiff --git a/worker/buildbot_worker/scripts/start.py b/worker/buildbot_worker/scripts/start.py\n--- a/worker/buildbot_worker/scripts/start.py\n+++ b/worker/buildbot_worker/scripts/start.py\n@@ -131,7 +131,11 @@\n             \"--logfile=twistd.log\",  # windows doesn't use the same default\n             \"--python=buildbot.tac\"]\n     if nodaemon:\n-        argv.extend(['--nodaemon'])\n+        argv.extend([\"--nodaemon\"])\n+        if platformType != 'win32':\n+            # windows doesn't use pidfile option.\n+            argv.extend([\"--pidfile=\"])\n+\n     sys.argv = argv\n \n     # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n", "issue": "Running with --nodaemon and PID files\nThis ticket is a migrated Trac ticket [3608](http://trac.buildbot.net/ticket/3608)\n\nPeople contributed to the original ticket: @unknown_contributor\nTicket created on: `Sep 12 2016`\nTicket last modified on: `Sep 12 2016`\n\n---\n\nBoth the master and the worker still use PID files while running with --nodaemon. I've had issues with workers running with --nodaemon not starting because of an old, stale PID file, corresponding to an actual process belonging to another user.\n\nThis can be thought to be inconsistent, and harms the writing ofreally simple non forking configuration files to manage the process through an external service manager (systemd, supervisord etc.).\n\nIt seems that the cousin ``twistd`` executable has a --pidfile argument, that can be used to mean \"no pid file\". This is explained notably in https://twistedmatrix.com/documents/current/core/howto/systemd.html.\n\nWe could expose that, or we could decide that --nodaemon implies no pid file.\n\nI believe this is true in Eight and Nine, and that a fix could be easily backported\n(marking this as minor, because it's easy to circumvent by putting appropriate rms in unit files or other confs)\n\n\n---\n\n\n\n", "before_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\nimport sys\nimport time\n\nfrom buildbot_worker.scripts import base\nfrom buildbot_worker.util import rewrap\n\n\nclass Follower(object):\n\n    def follow(self):\n        from twisted.internet import reactor\n        from buildbot_worker.scripts.logwatcher import LogWatcher\n        self.rc = 0\n        print(\"Following twistd.log until startup finished..\")\n        lw = LogWatcher(\"twistd.log\")\n        d = lw.start()\n        d.addCallbacks(self._success, self._failure)\n        reactor.run()\n        return self.rc\n\n    def _success(self, processtype):\n        from twisted.internet import reactor\n        print(\"The %s appears to have (re)started correctly.\" % processtype)\n        self.rc = 0\n        reactor.stop()\n\n    def _failure(self, why):\n        from twisted.internet import reactor\n        from buildbot_worker.scripts.logwatcher import WorkerTimeoutError\n        if why.check(WorkerTimeoutError):\n            print(rewrap(\"\"\"\\\n                The worker took more than 10 seconds to start and/or connect\n                to the buildmaster, so we were unable to confirm that it\n                started and connected correctly.\n                Please 'tail twistd.log' and look for a line that says\n                'message from master: attached' to verify correct startup.\n                If you see a bunch of messages like 'will retry in 6 seconds',\n                your worker might not have the correct hostname or portnumber\n                for the buildmaster, or the buildmaster might not be running.\n                If you see messages like\n                   'Failure: twisted.cred.error.UnauthorizedLogin'\n                then your worker might be using the wrong botname or password.\n                Please correct these problems and then restart the worker.\n                \"\"\"))\n        else:\n            print(rewrap(\"\"\"\\\n                Unable to confirm that the worker started correctly.\n                You may need to stop it, fix the config file, and restart.\n                \"\"\"))\n            print(why)\n        self.rc = 1\n        reactor.stop()\n\n\ndef startCommand(config):\n    basedir = config['basedir']\n    if not base.isWorkerDir(basedir):\n        return 1\n\n    return startWorker(basedir, config['quiet'], config['nodaemon'])\n\n\ndef startWorker(basedir, quiet, nodaemon):\n    \"\"\"\n    Start worker process.\n\n    Fork and start twisted application described in basedir buildbot.tac file.\n    Print it's log messages to stdout for a while and try to figure out if\n    start was successful.\n\n    If quiet or nodaemon parameters are True, or we are running on a win32\n    system, will not fork and log will not be printed to stdout.\n\n    @param  basedir: worker's basedir path\n    @param    quiet: don't display startup log messages\n    @param nodaemon: don't daemonize (stay in foreground)\n    @return: 0 if worker was successfully started,\n             1 if we are not sure that worker started successfully\n    \"\"\"\n\n    os.chdir(basedir)\n    if quiet or nodaemon:\n        return launch(nodaemon)\n\n    # we probably can't do this os.fork under windows\n    from twisted.python.runtime import platformType\n    if platformType == \"win32\":\n        return launch(nodaemon)\n\n    # fork a child to launch the daemon, while the parent process tails the\n    # logfile\n    if os.fork():\n        # this is the parent\n        rc = Follower().follow()\n        return rc\n    # this is the child: give the logfile-watching parent a chance to start\n    # watching it before we start the daemon\n    time.sleep(0.2)\n    launch(nodaemon)\n\n\ndef launch(nodaemon):\n    sys.path.insert(0, os.path.abspath(os.getcwd()))\n\n    # see if we can launch the application without actually having to\n    # spawn twistd, since spawning processes correctly is a real hassle\n    # on windows.\n    from twisted.python.runtime import platformType\n    argv = [\"twistd\",\n            \"--no_save\",\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n    if nodaemon:\n        argv.extend(['--nodaemon'])\n    sys.argv = argv\n\n    # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n    # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n    # windows.\n    from twisted import __version__\n    major, minor, ignored = __version__.split(\".\", 2)\n    major = int(major)\n    minor = int(minor)\n    if (platformType == \"win32\" and (major == 2 and minor < 5)):\n        from twisted.scripts import _twistw\n        run = _twistw.run\n    else:\n        from twisted.scripts import twistd\n        run = twistd.run\n    run()\n", "path": "worker/buildbot_worker/scripts/start.py"}, {"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\nimport sys\n\nfrom twisted.internet import protocol\nfrom twisted.internet import reactor\nfrom twisted.python.runtime import platformType\n\nfrom buildbot.scripts import base\nfrom buildbot.scripts.logwatcher import BuildmasterStartupError\nfrom buildbot.scripts.logwatcher import BuildmasterTimeoutError\nfrom buildbot.scripts.logwatcher import LogWatcher\nfrom buildbot.scripts.logwatcher import ReconfigError\nfrom buildbot.util import rewrap\n\n\nclass Follower:\n\n    def follow(self, basedir):\n        self.rc = 0\n        print(\"Following twistd.log until startup finished..\")\n        lw = LogWatcher(os.path.join(basedir, \"twistd.log\"))\n        d = lw.start()\n        d.addCallbacks(self._success, self._failure)\n        reactor.run()\n        return self.rc\n\n    def _success(self, _):\n        print(\"The buildmaster appears to have (re)started correctly.\")\n        self.rc = 0\n        reactor.stop()\n\n    def _failure(self, why):\n        if why.check(BuildmasterTimeoutError):\n            print(rewrap(\"\"\"\\\n                The buildmaster took more than 10 seconds to start, so we were\n                unable to confirm that it started correctly.\n                Please 'tail twistd.log' and look for a line that says\n                'BuildMaster is running' to verify correct startup.\n                \"\"\"))\n        elif why.check(ReconfigError):\n            print(rewrap(\"\"\"\\\n                The buildmaster appears to have encountered an error in the\n                master.cfg config file during startup.\n                Please inspect and fix master.cfg, then restart the\n                buildmaster.\n                \"\"\"))\n        elif why.check(BuildmasterStartupError):\n            print(rewrap(\"\"\"\\\n                The buildmaster startup failed. Please see 'twistd.log' for\n                possible reason.\n                \"\"\"))\n        else:\n            print(rewrap(\"\"\"\\\n                Unable to confirm that the buildmaster started correctly.\n                You may need to stop it, fix the config file, and restart.\n                \"\"\"))\n            print(why)\n        self.rc = 1\n        reactor.stop()\n\n\ndef launchNoDaemon(config):\n    os.chdir(config['basedir'])\n    sys.path.insert(0, os.path.abspath(config['basedir']))\n\n    argv = [\"twistd\",\n            \"--no_save\",\n            '--nodaemon',\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n    sys.argv = argv\n\n    # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n    # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n    # windows.\n    from twisted.scripts import twistd\n    twistd.run()\n\n\ndef launch(config):\n    os.chdir(config['basedir'])\n    sys.path.insert(0, os.path.abspath(config['basedir']))\n\n    # see if we can launch the application without actually having to\n    # spawn twistd, since spawning processes correctly is a real hassle\n    # on windows.\n    argv = [sys.executable,\n            \"-c\",\n            # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n            # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n            # windows.\n            \"from twisted.scripts import twistd; twistd.run()\",\n            \"--no_save\",\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n\n    # ProcessProtocol just ignores all output\n    proc = reactor.spawnProcess(\n        protocol.ProcessProtocol(), sys.executable, argv, env=os.environ)\n\n    if platformType == \"win32\":\n        with open(\"twistd.pid\", \"w\") as pidfile:\n            pidfile.write(\"{0}\".format(proc.pid))\n\n\ndef start(config):\n    if not base.isBuildmasterDir(config['basedir']):\n        return 1\n\n    if config['nodaemon']:\n        launchNoDaemon(config)\n        return 0\n\n    launch(config)\n\n    # We don't have tail on windows\n    if platformType == \"win32\" or config['quiet']:\n        return 0\n\n    # this is the parent\n    rc = Follower().follow(config['basedir'])\n    return rc\n", "path": "master/buildbot/scripts/start.py"}], "after_files": [{"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\nimport sys\nimport time\n\nfrom buildbot_worker.scripts import base\nfrom buildbot_worker.util import rewrap\n\n\nclass Follower(object):\n\n    def follow(self):\n        from twisted.internet import reactor\n        from buildbot_worker.scripts.logwatcher import LogWatcher\n        self.rc = 0\n        print(\"Following twistd.log until startup finished..\")\n        lw = LogWatcher(\"twistd.log\")\n        d = lw.start()\n        d.addCallbacks(self._success, self._failure)\n        reactor.run()\n        return self.rc\n\n    def _success(self, processtype):\n        from twisted.internet import reactor\n        print(\"The %s appears to have (re)started correctly.\" % processtype)\n        self.rc = 0\n        reactor.stop()\n\n    def _failure(self, why):\n        from twisted.internet import reactor\n        from buildbot_worker.scripts.logwatcher import WorkerTimeoutError\n        if why.check(WorkerTimeoutError):\n            print(rewrap(\"\"\"\\\n                The worker took more than 10 seconds to start and/or connect\n                to the buildmaster, so we were unable to confirm that it\n                started and connected correctly.\n                Please 'tail twistd.log' and look for a line that says\n                'message from master: attached' to verify correct startup.\n                If you see a bunch of messages like 'will retry in 6 seconds',\n                your worker might not have the correct hostname or portnumber\n                for the buildmaster, or the buildmaster might not be running.\n                If you see messages like\n                   'Failure: twisted.cred.error.UnauthorizedLogin'\n                then your worker might be using the wrong botname or password.\n                Please correct these problems and then restart the worker.\n                \"\"\"))\n        else:\n            print(rewrap(\"\"\"\\\n                Unable to confirm that the worker started correctly.\n                You may need to stop it, fix the config file, and restart.\n                \"\"\"))\n            print(why)\n        self.rc = 1\n        reactor.stop()\n\n\ndef startCommand(config):\n    basedir = config['basedir']\n    if not base.isWorkerDir(basedir):\n        return 1\n\n    return startWorker(basedir, config['quiet'], config['nodaemon'])\n\n\ndef startWorker(basedir, quiet, nodaemon):\n    \"\"\"\n    Start worker process.\n\n    Fork and start twisted application described in basedir buildbot.tac file.\n    Print it's log messages to stdout for a while and try to figure out if\n    start was successful.\n\n    If quiet or nodaemon parameters are True, or we are running on a win32\n    system, will not fork and log will not be printed to stdout.\n\n    @param  basedir: worker's basedir path\n    @param    quiet: don't display startup log messages\n    @param nodaemon: don't daemonize (stay in foreground)\n    @return: 0 if worker was successfully started,\n             1 if we are not sure that worker started successfully\n    \"\"\"\n\n    os.chdir(basedir)\n    if quiet or nodaemon:\n        return launch(nodaemon)\n\n    # we probably can't do this os.fork under windows\n    from twisted.python.runtime import platformType\n    if platformType == \"win32\":\n        return launch(nodaemon)\n\n    # fork a child to launch the daemon, while the parent process tails the\n    # logfile\n    if os.fork():\n        # this is the parent\n        rc = Follower().follow()\n        return rc\n    # this is the child: give the logfile-watching parent a chance to start\n    # watching it before we start the daemon\n    time.sleep(0.2)\n    launch(nodaemon)\n\n\ndef launch(nodaemon):\n    sys.path.insert(0, os.path.abspath(os.getcwd()))\n\n    # see if we can launch the application without actually having to\n    # spawn twistd, since spawning processes correctly is a real hassle\n    # on windows.\n    from twisted.python.runtime import platformType\n    argv = [\"twistd\",\n            \"--no_save\",\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n    if nodaemon:\n        argv.extend([\"--nodaemon\"])\n        if platformType != 'win32':\n            # windows doesn't use pidfile option.\n            argv.extend([\"--pidfile=\"])\n\n    sys.argv = argv\n\n    # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n    # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n    # windows.\n    from twisted import __version__\n    major, minor, ignored = __version__.split(\".\", 2)\n    major = int(major)\n    minor = int(minor)\n    if (platformType == \"win32\" and (major == 2 and minor < 5)):\n        from twisted.scripts import _twistw\n        run = _twistw.run\n    else:\n        from twisted.scripts import twistd\n        run = twistd.run\n    run()\n", "path": "worker/buildbot_worker/scripts/start.py"}, {"content": "# This file is part of Buildbot.  Buildbot is free software: you can\n# redistribute it and/or modify it under the terms of the GNU General Public\n# License as published by the Free Software Foundation, version 2.\n#\n# This program is distributed in the hope that it will be useful, but WITHOUT\n# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\n# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more\n# details.\n#\n# You should have received a copy of the GNU General Public License along with\n# this program; if not, write to the Free Software Foundation, Inc., 51\n# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n#\n# Copyright Buildbot Team Members\n\nfrom __future__ import absolute_import\nfrom __future__ import division\nfrom __future__ import print_function\n\nimport os\nimport sys\n\nfrom twisted.internet import protocol\nfrom twisted.internet import reactor\nfrom twisted.python.runtime import platformType\n\nfrom buildbot.scripts import base\nfrom buildbot.scripts.logwatcher import BuildmasterStartupError\nfrom buildbot.scripts.logwatcher import BuildmasterTimeoutError\nfrom buildbot.scripts.logwatcher import LogWatcher\nfrom buildbot.scripts.logwatcher import ReconfigError\nfrom buildbot.util import rewrap\n\n\nclass Follower:\n\n    def follow(self, basedir):\n        self.rc = 0\n        print(\"Following twistd.log until startup finished..\")\n        lw = LogWatcher(os.path.join(basedir, \"twistd.log\"))\n        d = lw.start()\n        d.addCallbacks(self._success, self._failure)\n        reactor.run()\n        return self.rc\n\n    def _success(self, _):\n        print(\"The buildmaster appears to have (re)started correctly.\")\n        self.rc = 0\n        reactor.stop()\n\n    def _failure(self, why):\n        if why.check(BuildmasterTimeoutError):\n            print(rewrap(\"\"\"\\\n                The buildmaster took more than 10 seconds to start, so we were\n                unable to confirm that it started correctly.\n                Please 'tail twistd.log' and look for a line that says\n                'BuildMaster is running' to verify correct startup.\n                \"\"\"))\n        elif why.check(ReconfigError):\n            print(rewrap(\"\"\"\\\n                The buildmaster appears to have encountered an error in the\n                master.cfg config file during startup.\n                Please inspect and fix master.cfg, then restart the\n                buildmaster.\n                \"\"\"))\n        elif why.check(BuildmasterStartupError):\n            print(rewrap(\"\"\"\\\n                The buildmaster startup failed. Please see 'twistd.log' for\n                possible reason.\n                \"\"\"))\n        else:\n            print(rewrap(\"\"\"\\\n                Unable to confirm that the buildmaster started correctly.\n                You may need to stop it, fix the config file, and restart.\n                \"\"\"))\n            print(why)\n        self.rc = 1\n        reactor.stop()\n\n\ndef launchNoDaemon(config):\n    os.chdir(config['basedir'])\n    sys.path.insert(0, os.path.abspath(config['basedir']))\n\n    argv = [\"twistd\",\n            \"--no_save\",\n            \"--nodaemon\",\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n\n    if platformType != 'win32':\n        # windows doesn't use pidfile option.\n        argv.extend([\"--pidfile=\"])\n\n    sys.argv = argv\n\n    # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n    # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n    # windows.\n    from twisted.scripts import twistd\n    twistd.run()\n\n\ndef launch(config):\n    os.chdir(config['basedir'])\n    sys.path.insert(0, os.path.abspath(config['basedir']))\n\n    # see if we can launch the application without actually having to\n    # spawn twistd, since spawning processes correctly is a real hassle\n    # on windows.\n    argv = [sys.executable,\n            \"-c\",\n            # this is copied from bin/twistd. twisted-2.0.0 through 2.4.0 use\n            # _twistw.run . Twisted-2.5.0 and later use twistd.run, even for\n            # windows.\n            \"from twisted.scripts import twistd; twistd.run()\",\n            \"--no_save\",\n            \"--logfile=twistd.log\",  # windows doesn't use the same default\n            \"--python=buildbot.tac\"]\n\n    # ProcessProtocol just ignores all output\n    proc = reactor.spawnProcess(\n        protocol.ProcessProtocol(), sys.executable, argv, env=os.environ)\n\n    if platformType == \"win32\":\n        with open(\"twistd.pid\", \"w\") as pidfile:\n            pidfile.write(\"{0}\".format(proc.pid))\n\n\ndef start(config):\n    if not base.isBuildmasterDir(config['basedir']):\n        return 1\n\n    if config['nodaemon']:\n        launchNoDaemon(config)\n        return 0\n\n    launch(config)\n\n    # We don't have tail on windows\n    if platformType == \"win32\" or config['quiet']:\n        return 0\n\n    # this is the parent\n    rc = Follower().follow(config['basedir'])\n    return rc\n", "path": "master/buildbot/scripts/start.py"}]}