We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Less violent way of closing player when stream ends
Currently streamlink uses SIGKILL to close the player when a stream ends. This prevents the player from doing its own cleanup. For example, mpv leaves DPMS/screensaver disabled because of this. I know there is --player-no-close option, but that has an unwanted side-effect of not closing the player immediately in some situations.

I suggest fixing it by using SIGTERM instead:
```diff
diff -bur streamlink-0.1.0-orig/src/streamlink_cli/output.py streamlink-0.1.0/src/streamlink_cli/output.py
--- streamlink-0.1.0-orig/src/streamlink_cli/output.py  2016-11-21 21:56:29.000000000 +0200
+++ streamlink-0.1.0/src/streamlink_cli/output.py       2016-12-08 22:08:23.000000000 +0200
@@ -161,7 +161,7 @@
 
         if self.kill:
             with ignored(Exception):
-                self.player.kill()
+                self.player.terminate()
         self.player.wait()
 
     def _write(self, data):
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/streamlink_cli/output.py`
Content:
```
1 import os
2 import shlex
3 import subprocess
4 import sys
5 
6 from time import sleep
7 
8 import re
9 
10 from .compat import is_win32, stdout
11 from .constants import DEFAULT_PLAYER_ARGUMENTS
12 from .utils import ignored
13 
14 if is_win32:
15     import msvcrt
16 
17 
18 class Output(object):
19     def __init__(self):
20         self.opened = False
21 
22     def open(self):
23         self._open()
24         self.opened = True
25 
26     def close(self):
27         if self.opened:
28             self._close()
29 
30         self.opened = False
31 
32     def write(self, data):
33         if not self.opened:
34             raise IOError("Output is not opened")
35 
36         return self._write(data)
37 
38     def _open(self):
39         pass
40 
41     def _close(self):
42         pass
43 
44     def _write(self, data):
45         pass
46 
47 
48 class FileOutput(Output):
49     def __init__(self, filename=None, fd=None):
50         super(FileOutput, self).__init__()
51         self.filename = filename
52         self.fd = fd
53 
54     def _open(self):
55         if self.filename:
56             self.fd = open(self.filename, "wb")
57 
58         if is_win32:
59             msvcrt.setmode(self.fd.fileno(), os.O_BINARY)
60 
61     def _close(self):
62         if self.fd is not stdout:
63             self.fd.close()
64 
65     def _write(self, data):
66         self.fd.write(data)
67 
68 
69 class PlayerOutput(Output):
70     def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=False,
71                  namedpipe=None):
72         super(PlayerOutput, self).__init__()
73         self.cmd = cmd
74         self.args = args
75         self.kill = kill
76         self.call = call
77         self.quiet = quiet
78 
79         self.filename = filename
80         self.namedpipe = namedpipe
81         self.http = http
82 
83         if self.namedpipe or self.filename or self.http:
84             self.stdin = sys.stdin
85         else:
86             self.stdin = subprocess.PIPE
87 
88         if self.quiet:
89             self.stdout = open(os.devnull, "w")
90             self.stderr = open(os.devnull, "w")
91         else:
92             self.stdout = sys.stdout
93             self.stderr = sys.stderr
94 
95     @property
96     def running(self):
97         sleep(0.5)
98         self.player.poll()
99         return self.player.returncode is None
100 
101     def _create_arguments(self):
102         if self.namedpipe:
103             filename = self.namedpipe.path
104         elif self.filename:
105             filename = self.filename
106         elif self.http:
107             filename = self.http.url
108         else:
109             filename = "-"
110 
111         args = self.args.format(filename=filename)
112         cmd = self.cmd
113         if is_win32:
114             return cmd + " " + args
115 
116         return shlex.split(cmd) + shlex.split(args)
117 
118     def _open(self):
119         try:
120             if self.call and self.filename:
121                 self._open_call()
122             else:
123                 self._open_subprocess()
124         finally:
125             if self.quiet:
126                 # Output streams no longer needed in parent process
127                 self.stdout.close()
128                 self.stderr.close()
129 
130     def _open_call(self):
131         subprocess.call(self._create_arguments(),
132                         stdout=self.stdout,
133                         stderr=self.stderr)
134 
135     def _open_subprocess(self):
136         # Force bufsize=0 on all Python versions to avoid writing the
137         # unflushed buffer when closing a broken input pipe
138         self.player = subprocess.Popen(self._create_arguments(),
139                                        stdin=self.stdin, bufsize=0,
140                                        stdout=self.stdout,
141                                        stderr=self.stderr)
142         # Wait 0.5 seconds to see if program exited prematurely
143         if not self.running:
144             raise OSError("Process exited prematurely")
145 
146         if self.namedpipe:
147             self.namedpipe.open("wb")
148         elif self.http:
149             self.http.open()
150 
151     def _close(self):
152         # Close input to the player first to signal the end of the
153         # stream and allow the player to terminate of its own accord
154         if self.namedpipe:
155             self.namedpipe.close()
156         elif self.http:
157             self.http.close()
158         elif not self.filename:
159             self.player.stdin.close()
160 
161         if self.kill:
162             with ignored(Exception):
163                 self.player.kill()
164         self.player.wait()
165 
166     def _write(self, data):
167         if self.namedpipe:
168             self.namedpipe.write(data)
169         elif self.http:
170             self.http.write(data)
171         else:
172             self.player.stdin.write(data)
173 
174 
175 __all__ = ["PlayerOutput", "FileOutput"]
176
```
--- 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/src/streamlink_cli/output.py b/src/streamlink_cli/output.py
--- a/src/streamlink_cli/output.py
+++ b/src/streamlink_cli/output.py
@@ -67,6 +67,8 @@
 
 
 class PlayerOutput(Output):
+    PLAYER_TERMINATE_TIMEOUT = 10.0
+
     def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=False,
                  namedpipe=None):
         super(PlayerOutput, self).__init__()
@@ -160,7 +162,15 @@
 
         if self.kill:
             with ignored(Exception):
-                self.player.kill()
+                self.player.terminate()
+                if not is_win32:
+                    t, timeout = 0.0, self.PLAYER_TERMINATE_TIMEOUT
+                    while not self.player.poll() and t < timeout:
+                        sleep(0.5)
+                        t += 0.5
+
+                    if not self.player.returncode:
+                        self.player.kill()
         self.player.wait()
 
     def _write(self, data):

{"golden_diff": "diff --git a/src/streamlink_cli/output.py b/src/streamlink_cli/output.py\n--- a/src/streamlink_cli/output.py\n+++ b/src/streamlink_cli/output.py\n@@ -67,6 +67,8 @@\n \n \n class PlayerOutput(Output):\n+    PLAYER_TERMINATE_TIMEOUT = 10.0\n+\n     def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=False,\n                  namedpipe=None):\n         super(PlayerOutput, self).__init__()\n@@ -160,7 +162,15 @@\n \n         if self.kill:\n             with ignored(Exception):\n-                self.player.kill()\n+                self.player.terminate()\n+                if not is_win32:\n+                    t, timeout = 0.0, self.PLAYER_TERMINATE_TIMEOUT\n+                    while not self.player.poll() and t < timeout:\n+                        sleep(0.5)\n+                        t += 0.5\n+\n+                    if not self.player.returncode:\n+                        self.player.kill()\n         self.player.wait()\n \n     def _write(self, data):\n", "issue": "Less violent way of closing player when stream ends\nCurrently streamlink uses SIGKILL to close the player when a stream ends. This prevents the player from doing its own cleanup. For example, mpv leaves DPMS/screensaver disabled because of this. I know there is --player-no-close option, but that has an unwanted side-effect of not closing the player immediately in some situations.\r\n\r\nI suggest fixing it by using SIGTERM instead:\r\n```diff\r\ndiff -bur streamlink-0.1.0-orig/src/streamlink_cli/output.py streamlink-0.1.0/src/streamlink_cli/output.py\r\n--- streamlink-0.1.0-orig/src/streamlink_cli/output.py  2016-11-21 21:56:29.000000000 +0200\r\n+++ streamlink-0.1.0/src/streamlink_cli/output.py       2016-12-08 22:08:23.000000000 +0200\r\n@@ -161,7 +161,7 @@\r\n \r\n         if self.kill:\r\n             with ignored(Exception):\r\n-                self.player.kill()\r\n+                self.player.terminate()\r\n         self.player.wait()\r\n \r\n     def _write(self, data):\r\n```\n", "before_files": [{"content": "import os\nimport shlex\nimport subprocess\nimport sys\n\nfrom time import sleep\n\nimport re\n\nfrom .compat import is_win32, stdout\nfrom .constants import DEFAULT_PLAYER_ARGUMENTS\nfrom .utils import ignored\n\nif is_win32:\n    import msvcrt\n\n\nclass Output(object):\n    def __init__(self):\n        self.opened = False\n\n    def open(self):\n        self._open()\n        self.opened = True\n\n    def close(self):\n        if self.opened:\n            self._close()\n\n        self.opened = False\n\n    def write(self, data):\n        if not self.opened:\n            raise IOError(\"Output is not opened\")\n\n        return self._write(data)\n\n    def _open(self):\n        pass\n\n    def _close(self):\n        pass\n\n    def _write(self, data):\n        pass\n\n\nclass FileOutput(Output):\n    def __init__(self, filename=None, fd=None):\n        super(FileOutput, self).__init__()\n        self.filename = filename\n        self.fd = fd\n\n    def _open(self):\n        if self.filename:\n            self.fd = open(self.filename, \"wb\")\n\n        if is_win32:\n            msvcrt.setmode(self.fd.fileno(), os.O_BINARY)\n\n    def _close(self):\n        if self.fd is not stdout:\n            self.fd.close()\n\n    def _write(self, data):\n        self.fd.write(data)\n\n\nclass PlayerOutput(Output):\n    def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=False,\n                 namedpipe=None):\n        super(PlayerOutput, self).__init__()\n        self.cmd = cmd\n        self.args = args\n        self.kill = kill\n        self.call = call\n        self.quiet = quiet\n\n        self.filename = filename\n        self.namedpipe = namedpipe\n        self.http = http\n\n        if self.namedpipe or self.filename or self.http:\n            self.stdin = sys.stdin\n        else:\n            self.stdin = subprocess.PIPE\n\n        if self.quiet:\n            self.stdout = open(os.devnull, \"w\")\n            self.stderr = open(os.devnull, \"w\")\n        else:\n            self.stdout = sys.stdout\n            self.stderr = sys.stderr\n\n    @property\n    def running(self):\n        sleep(0.5)\n        self.player.poll()\n        return self.player.returncode is None\n\n    def _create_arguments(self):\n        if self.namedpipe:\n            filename = self.namedpipe.path\n        elif self.filename:\n            filename = self.filename\n        elif self.http:\n            filename = self.http.url\n        else:\n            filename = \"-\"\n\n        args = self.args.format(filename=filename)\n        cmd = self.cmd\n        if is_win32:\n            return cmd + \" \" + args\n\n        return shlex.split(cmd) + shlex.split(args)\n\n    def _open(self):\n        try:\n            if self.call and self.filename:\n                self._open_call()\n            else:\n                self._open_subprocess()\n        finally:\n            if self.quiet:\n                # Output streams no longer needed in parent process\n                self.stdout.close()\n                self.stderr.close()\n\n    def _open_call(self):\n        subprocess.call(self._create_arguments(),\n                        stdout=self.stdout,\n                        stderr=self.stderr)\n\n    def _open_subprocess(self):\n        # Force bufsize=0 on all Python versions to avoid writing the\n        # unflushed buffer when closing a broken input pipe\n        self.player = subprocess.Popen(self._create_arguments(),\n                                       stdin=self.stdin, bufsize=0,\n                                       stdout=self.stdout,\n                                       stderr=self.stderr)\n        # Wait 0.5 seconds to see if program exited prematurely\n        if not self.running:\n            raise OSError(\"Process exited prematurely\")\n\n        if self.namedpipe:\n            self.namedpipe.open(\"wb\")\n        elif self.http:\n            self.http.open()\n\n    def _close(self):\n        # Close input to the player first to signal the end of the\n        # stream and allow the player to terminate of its own accord\n        if self.namedpipe:\n            self.namedpipe.close()\n        elif self.http:\n            self.http.close()\n        elif not self.filename:\n            self.player.stdin.close()\n\n        if self.kill:\n            with ignored(Exception):\n                self.player.kill()\n        self.player.wait()\n\n    def _write(self, data):\n        if self.namedpipe:\n            self.namedpipe.write(data)\n        elif self.http:\n            self.http.write(data)\n        else:\n            self.player.stdin.write(data)\n\n\n__all__ = [\"PlayerOutput\", \"FileOutput\"]\n", "path": "src/streamlink_cli/output.py"}], "after_files": [{"content": "import os\nimport shlex\nimport subprocess\nimport sys\n\nfrom time import sleep\n\nimport re\n\nfrom .compat import is_win32, stdout\nfrom .constants import DEFAULT_PLAYER_ARGUMENTS\nfrom .utils import ignored\n\nif is_win32:\n    import msvcrt\n\n\nclass Output(object):\n    def __init__(self):\n        self.opened = False\n\n    def open(self):\n        self._open()\n        self.opened = True\n\n    def close(self):\n        if self.opened:\n            self._close()\n\n        self.opened = False\n\n    def write(self, data):\n        if not self.opened:\n            raise IOError(\"Output is not opened\")\n\n        return self._write(data)\n\n    def _open(self):\n        pass\n\n    def _close(self):\n        pass\n\n    def _write(self, data):\n        pass\n\n\nclass FileOutput(Output):\n    def __init__(self, filename=None, fd=None):\n        super(FileOutput, self).__init__()\n        self.filename = filename\n        self.fd = fd\n\n    def _open(self):\n        if self.filename:\n            self.fd = open(self.filename, \"wb\")\n\n        if is_win32:\n            msvcrt.setmode(self.fd.fileno(), os.O_BINARY)\n\n    def _close(self):\n        if self.fd is not stdout:\n            self.fd.close()\n\n    def _write(self, data):\n        self.fd.write(data)\n\n\nclass PlayerOutput(Output):\n    PLAYER_TERMINATE_TIMEOUT = 10.0\n\n    def __init__(self, cmd, args=DEFAULT_PLAYER_ARGUMENTS, filename=None, quiet=True, kill=True, call=False, http=False,\n                 namedpipe=None):\n        super(PlayerOutput, self).__init__()\n        self.cmd = cmd\n        self.args = args\n        self.kill = kill\n        self.call = call\n        self.quiet = quiet\n\n        self.filename = filename\n        self.namedpipe = namedpipe\n        self.http = http\n\n        if self.namedpipe or self.filename or self.http:\n            self.stdin = sys.stdin\n        else:\n            self.stdin = subprocess.PIPE\n\n        if self.quiet:\n            self.stdout = open(os.devnull, \"w\")\n            self.stderr = open(os.devnull, \"w\")\n        else:\n            self.stdout = sys.stdout\n            self.stderr = sys.stderr\n\n    @property\n    def running(self):\n        sleep(0.5)\n        self.player.poll()\n        return self.player.returncode is None\n\n    def _create_arguments(self):\n        if self.namedpipe:\n            filename = self.namedpipe.path\n        elif self.filename:\n            filename = self.filename\n        elif self.http:\n            filename = self.http.url\n        else:\n            filename = \"-\"\n\n        args = self.args.format(filename=filename)\n        cmd = self.cmd\n        if is_win32:\n            return cmd + \" \" + args\n\n        return shlex.split(cmd) + shlex.split(args)\n\n    def _open(self):\n        try:\n            if self.call and self.filename:\n                self._open_call()\n            else:\n                self._open_subprocess()\n        finally:\n            if self.quiet:\n                # Output streams no longer needed in parent process\n                self.stdout.close()\n                self.stderr.close()\n\n    def _open_call(self):\n        subprocess.call(self._create_arguments(),\n                        stdout=self.stdout,\n                        stderr=self.stderr)\n\n    def _open_subprocess(self):\n        # Force bufsize=0 on all Python versions to avoid writing the\n        # unflushed buffer when closing a broken input pipe\n        self.player = subprocess.Popen(self._create_arguments(),\n                                       stdin=self.stdin, bufsize=0,\n                                       stdout=self.stdout,\n                                       stderr=self.stderr)\n        # Wait 0.5 seconds to see if program exited prematurely\n        if not self.running:\n            raise OSError(\"Process exited prematurely\")\n\n        if self.namedpipe:\n            self.namedpipe.open(\"wb\")\n        elif self.http:\n            self.http.open()\n\n    def _close(self):\n        # Close input to the player first to signal the end of the\n        # stream and allow the player to terminate of its own accord\n        if self.namedpipe:\n            self.namedpipe.close()\n        elif self.http:\n            self.http.close()\n        elif not self.filename:\n            self.player.stdin.close()\n\n        if self.kill:\n            with ignored(Exception):\n                self.player.terminate()\n                if not is_win32:\n                    t, timeout = 0.0, self.PLAYER_TERMINATE_TIMEOUT\n                    while not self.player.poll() and t < timeout:\n                        sleep(0.5)\n                        t += 0.5\n\n                    if not self.player.returncode:\n                        self.player.kill()\n        self.player.wait()\n\n    def _write(self, data):\n        if self.namedpipe:\n            self.namedpipe.write(data)\n        elif self.http:\n            self.http.write(data)\n        else:\n            self.player.stdin.write(data)\n\n\n__all__ = [\"PlayerOutput\", \"FileOutput\"]\n", "path": "src/streamlink_cli/output.py"}]}