# Buggy code
async def send(self, message):
    protocol = self.protocol
    message_type = message["type"]

    if not protocol.writable:
        await protocol.writable_event.wait()

    if not self.response_started:
        # Sending response status line and headers
        if message_type != "http.response.start":
            msg = "Expected ASGI message 'http.response.start', but got '%s'."
            raise RuntimeError(msg % message_type)

        self.response_started = True

        status_code = message["status"]
        headers = message.get("headers", [])

        if protocol.access_logs:
            protocol.logger.info(
                '%s - "%s %s HTTP/%s" %d',
                self.scope["server"][0],
                self.scope["method"],
                self.scope["path"],
                self.scope["http_version"],
                status_code,
            )

        # Write response status line and headers
        content = [STATUS_LINE[status_code], DEFAULT_HEADERS]

        for name, value in headers:
            name = name.lower()
            if name == b"content-length" and self.chunked_encoding is None:
                self.expected_content_length = int(value.decode())
                self.chunked_encoding = False
            elif name == b"transfer-encoding" and value.lower() == b"chunked":
                self.chunked_encoding = True
            elif name == b"connection" and value.lower() == b"close":
                self.keep_alive = False
            content.extend([name, b": ", value, b"\r\n"])

        if self.chunked_encoding is None:
            # Neither content-length nor transfer-encoding specified
            self.chunked_encoding = True
            content.append(b"transfer-encoding: chunked\r\n")

        content.append(b"\r\n")
        protocol.transport.write(b"".join(content))

    elif not self.response_complete:
        # Sending response body
        if message_type != "http.response.body":
            msg = "Expected ASGI message 'http.response.body', but got '%s'."
            raise RuntimeError(msg % message_type)

        body = message.get("body", b"")
        more_body = message.get("more_body", False)

        # Write response body
        if self.chunked_encoding:
            content = [b"%x\r\n" % len(body), body, b"\r\n"]
            if not more_body:
                content.append(b"0\r\n\r\n")
            protocol.transport.write(b"".join(content))
        else:
            num_bytes = len(body)
            if num_bytes > self.expected_content_length:
                raise RuntimeError("Response content longer than Content-Length")
            else:
                self.expected_content_length -= num_bytes
            protocol.transport.write(body)

        # Handle response completion
        if not more_body:
            if self.expected_content_length != 0:
                raise RuntimeError("Response content shorter than Content-Length")
            self.response_complete = True
            if not self.keep_alive:
                protocol.transport.close()
            else:
                protocol.resume_reading()
    else:
        # Response already sent
        msg = "Unexpected ASGI message '%s' sent, after response already completed."
        raise RuntimeError(msg % message_type)


# Traceback (RuntimeError)
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/httptools.py", line 196, in run_asgi
result = await asgi(self.receive, self.send)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
await self.handle(body)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/usr/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
return self.func(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/channels/http.py", line 229, in handle
self.send(response_message)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
return call_result.result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/home/chillar/.virtualenvs/library/lib/python3.6/site-packages/uvicorn/protocols/http/httptools.py", line 308, in send
protocol.transport.write(body)
File "uvloop/handles/stream.pyx", line 636, in uvloop.loop.UVStream.write
File "uvloop/handles/handle.pyx", line 165, in uvloop.loop.UVHandle._ensure_alive
RuntimeError: unable to perform operation on <TCPTransport closed=True reading=False 0x1a48ad8>; the handler is closed

# Fixed code
async def send(self, message):
    protocol = self.protocol
    message_type = message["type"]

    if self.disconnected:
        return

    if not protocol.writable:
        await protocol.writable_event.wait()

    if not self.response_started:
        # Sending response status line and headers
        if message_type != "http.response.start":
            msg = "Expected ASGI message 'http.response.start', but got '%s'."
            raise RuntimeError(msg % message_type)

        self.response_started = True

        status_code = message["status"]
        headers = message.get("headers", [])

        if protocol.access_logs:
            protocol.logger.info(
                '%s - "%s %s HTTP/%s" %d',
                self.scope["server"][0],
                self.scope["method"],
                self.scope["path"],
                self.scope["http_version"],
                status_code,
            )

        # Write response status line and headers
        content = [STATUS_LINE[status_code], DEFAULT_HEADERS]

        for name, value in headers:
            name = name.lower()
            if name == b"content-length" and self.chunked_encoding is None:
                self.expected_content_length = int(value.decode())
                self.chunked_encoding = False
            elif name == b"transfer-encoding" and value.lower() == b"chunked":
                self.chunked_encoding = True
            elif name == b"connection" and value.lower() == b"close":
                self.keep_alive = False
            content.extend([name, b": ", value, b"\r\n"])

        if self.chunked_encoding is None:
            # Neither content-length nor transfer-encoding specified
            self.chunked_encoding = True
            content.append(b"transfer-encoding: chunked\r\n")

        content.append(b"\r\n")
        protocol.transport.write(b"".join(content))

    elif not self.response_complete:
        # Sending response body
        if message_type != "http.response.body":
            msg = "Expected ASGI message 'http.response.body', but got '%s'."
            raise RuntimeError(msg % message_type)

        body = message.get("body", b"")
        more_body = message.get("more_body", False)

        # Write response body
        if self.chunked_encoding:
            content = [b"%x\r\n" % len(body), body, b"\r\n"]
            if not more_body:
                content.append(b"0\r\n\r\n")
            protocol.transport.write(b"".join(content))
        else:
            num_bytes = len(body)
            if num_bytes > self.expected_content_length:
                raise RuntimeError("Response content longer than Content-Length")
            else:
                self.expected_content_length -= num_bytes
            protocol.transport.write(body)

        # Handle response completion
        if not more_body:
            if self.expected_content_length != 0:
                raise RuntimeError("Response content shorter than Content-Length")
            self.response_complete = True
            if not self.keep_alive:
                protocol.transport.close()
            else:
                protocol.resume_reading()
    else:
        # Response already sent
        msg = "Unexpected ASGI message '%s' sent, after response already completed."
        raise RuntimeError(msg % message_type)