Hi Bastian,

thanks a lot for your help. I have already opened a bug report on Launchpad: 
https://bugs.launchpad.net/ubuntu/+source/reprepro/+bug/2047775, but I got no 
answer so far. Unfortunately, the proposed change does not work properly when 
mirroring the main component of the Ubuntu Jammy repository:

Shutting down aptmethods...
Installing (and possibly deleting) packages...
/*stdin*\ : Read error (39) : premature end
Segmentation fault (core dumped)

The best result, we were able to achieve, was to solely modify the timeout 
entry in the poll function from 0 to -1 and to keep the rest of the code as it 
is. This solves the hanging issue, but causes "/*stdin*\ : Read error (39) : 
premature end". Fortunately, the exports succeeds and seems to be ok. We are 
currently not able to remove the "Premature End" error and have no idea where 
it is being caused. We cannot guarantee the fully correctness of the following 
code. We are already using it in practice. It looks good so far:

static inline retvalue drain_pipe_fd(struct compressedfile *file, int *errno_p, 
const char **msg_p) {
        int e = 0;
        struct pollfd pollfd = {
                file->fd,
                POLLIN,
                0
        };
        unsigned char buffer[4096] = {};
        while ((e = poll(&pollfd, 1, -1)) > 0) {
                e = read(file->fd, buffer, 4096);
                if (e <= 0)
                        break;
        }
        if (e < 0) {
                *errno_p = e;
                *msg_p = strerror(file->error);
                return RET_ERRNO(e);
        }
        return RET_OK;
}

static retvalue uncompress_commonclose(struct compressedfile *file, int 
*errno_p, const char **msg_p) {
        retvalue result;
        int ret;
        int e;
        pid_t pid;
        int status;
        int output_fd;
#define ERRORBUFFERSIZE 100
        static char errorbuffer[ERRORBUFFERSIZE];

        if (file == NULL)
                return RET_OK;

        if (file->external) {
                free(file->intermediate.buffer);
                if (file->pipeinfd != -1)
                        (void)close(file->pipeinfd);
                // Drain the child's stdout in the unlikely case it's blocking 
on it
                e = drain_pipe_fd(file, errno_p, msg_p);
                if (e != RET_OK)
                        return e;
                output_fd = file->fd;
                file->fd = file->infd;
                result = RET_OK;
                if (file->pid <= 0) {
                        (void)close(output_fd);
                        return RET_OK;
                }
                do {
                        if (interrupted()) {
                                *errno_p = EINTR;
                                *msg_p = "Interrupted";
                                result = RET_ERROR_INTERRUPTED;
                        }
                        pid = waitpid(file->pid, &status, 0);
                        e = errno;
                } while (pid == -1 && (e == EINTR || e == EAGAIN));
                (void)close(output_fd);
        [...]
}

Regards,
Christoph

Reply via email to