def _handle_stdout_event(self, fd, events):
        """Eventhandler for stdout"""

        assert fd == self.fd_stdout

        if events & self.ioloop.READ:
            # got data ready to read
            data = ''

            # Now basically we have two cases: either the client supports
            # HTTP/1.1 in which case we can stream the answer in chunked mode
            # in HTTP/1.0 we need to send a content-length and thus buffer the complete output
            if self.request.supports_http_1_1():
                if not self.headers_sent:
                    self.sent_chunks = True
                    self.headers.update({'Date': get_date_header(), 'Transfer-Encoding': 'chunked'})
                    data = 'HTTP/1.1 200 OK\r\n' + '\r\n'.join([ k + ': ' + v for k, v in self.headers.items()]) + '\r\n\r\n'

                    if self.output_prelude:
                        data += hex(len(self.output_prelude))[2:] + "\r\n" # cut off 0x
                        data += self.output_prelude + "\r\n"

                    self.headers_sent = True

                payload = os.read(fd, 8192)
                if events & self.ioloop.ERROR: # there might be data remaining in the buffer if we got HUP, get it all
                    remainder = True
                    while remainder != '': # until EOF
                        remainder = os.read(fd, 8192)
                        payload += remainder

                data += hex(len(payload))[2:] + "\r\n" # cut off 0x
                data += payload + "\r\n"

            else:
                if not self.headers_sent:
                    # Use the over-eager blocking read that will get everything until we hit EOF
                    # this might actually be somewhat dangerous as noted in the subprocess documentation
                    # and lead to a deadlock. This is only a legacy mode for HTTP/1.0 clients anyway,
                    # so we might want to remove it entirely anyways
                    payload = self.process.stdout.read()
                    self.headers.update({'Date': get_date_header(), 'Content-Length': str(len(payload))})
                    data = 'HTTP/1.0 200 OK\r\n' + '\r\n'.join([ k + ': ' + v for k, v in self.headers.items()]) + '\r\n\r\n'
                    self.headers_sent = True
                    data += self.output_prelude + payload
                else:
                    # this is actually somewhat illegal as it messes with content-length but 
                    # it shouldn't happen anyways, as the read above should have read anything
                    # python docs say this can happen on ttys...
                    logger.error("This should not happen")
                    data = self.process.stdout.read()

            if len(data) == 8200:
                self.number_of_8k_chunks_sent += 1
            else:
                if self.number_of_8k_chunks_sent > 0:
                    logger.debug('Sent %d * 8192 bytes', self.number_of_8k_chunks_sent)
                    self.number_of_8k_chunks_sent = 0

                logger.debug('Sending stdout to client %d bytes: %r', len(data), data[:20])
            self.request.write(data)

        # now we can also have an error. This is because tornado maps HUP onto error
        # therefore, no elif here!
        if events & self.ioloop.ERROR:
            logger.debug('Error on stdout')
            # ensure file is closed
            if not self.process.stdout.closed:
                self.process.stdout.close()
            # remove handler
            self.ioloop.remove_handler(self.fd_stdout)
            # if all fds are closed, we can finish
            return self._graceful_finish()
Eventhandler for stdout