copy_to is a dict(in: out). When any in is ready to read, data is read
    from it and writen in its out. When any in is closed, it's removed from
    copy_to. finished is a pipe; when data comes from the read end, or when
    no more ins are present, the loop finishes.

def copy_loop (copy_to, finished=None, buf_len=10240):
    """copy_to is a dict(in: out). When any in is ready to read, data is read
    from it and writen in its out. When any in is closed, it's removed from
    copy_to. finished is a pipe; when data comes from the read end, or when
    no more ins are present, the loop finishes."""
    if finished is not None:
        copy_to[finished]= None

    # NOTE:
    # os.sendfile (self.dst, self.src, None, 0)
    # OSError: [Errno 22] Invalid argument
    # and splice() is not available
    # so, copy by hand
    selector = DefaultSelector ()
    for src in copy_to.keys ():
        if (     not isinstance (src, int)
                and (   getattr (src, 'fileno', None) is None
                    or not isinstance (src.fileno(), int)) ):
            logger.debug ('type mismatch: %s', src)
        else:
            logger.debug ("registering %s for read", src)
            # if finished is also one of the srcs, then register() complains
            try:
                selector.register (src, EVENT_READ)
            except KeyError:
                pass

    def close_file (f):
        if f in copy_to:
            del copy_to[f]

        try:
            selector.unregister (i)
        except KeyError:
            pass

        close (f)

    while len (copy_to)>0:
        logger.debug (copy_to)

        events= selector.select ()
        for key, _ in events:
            logger.debug ("%s is ready to read", key)
            i= key.fileobj

            # for error in e:
            #     logger.debug ('%s error')
                # TODO: what?

            o= copy_to[i]

            try:
                data= read (i, buf_len)
                logger.debug2 ('%s -> %s: %s', i, o, data)

            # ValueError: read of closed file
            except (OSError, ValueError) as e:
                logger.debug ('stopping copying for %s', i)
                logger.debug (traceback.format_exc ())
                close_file (i)
                break
            else:
                if len (data)==0:
                    logger.debug ('stopping copying for %s, no more data', i)
                    close_file (i)

                    if finished is not None and i==finished:
                        logger.debug ('finishing')
                        # quite a hack :)
                        copy_to= {}

                        break
                else:
                    write (o, data)

    selector.close ()
    logger.debug ('over and out')