Comment 3 for bug 2000871

Revision history for this message
Adam Reichold (adamreichold) wrote (last edit ):

Hello again,

the salient part of the log is

newfstatat(AT_FDCWD, "/tmp", {st_mode=S_IFDIR|0700, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "/tmp", O_RDWR|O_CLOEXEC|O_TMPFILE, 0600) = 26
lseek(26, 0, SEEK_SET) = 0
getrandom("\x42\x75\x62\x49\xd0\x70\x54\x66\x1c\x97\xee\x3d\x9c\xbb\x7c\x95\x9e\x5e\x58\x33\x03\xf2\x50\x4b\x58\x12\xb3\xd0\xa3\xab\xb7\x2d"..., 256, 0) = 256
getrandom("\x4e\x80\xff\xd5\x64\x88\xb6\x26\x00\x59\xa3\x7c\xea\x3c\xa6\xcd\x14\xc3\xae\xe3\x10\x14\x62\xa1\x46\xbe\xf3\x27\x38\x13\x28\x28"..., 256, 0) = 256
getrandom("\xc3\x75\x28\x54\xde\xc9\xe0\xfd\x3a\xe3\xd0\x65\x2f\x3d\x4a\xf1\xdb\x2e\xe6\x3d\x74\x96\xc4\x30\x8a\x44\x6d\xe8\x61\x6f\x05\x5c"..., 256, 0) = 256
getrandom("\x51\x93\xb0\xa6\x69\xba\x10\x57\x60\xff\xc9\xc8\xb1\x18\x52\x67\x2d\x7e\x42\x29\xf9\xb4\x58\x74\xda\x84\xc4\x2a\xf0\x6d\x2b\x35"..., 256, 0) = 256
getrandom("\x4f\xbc\x78\x61\xa3\x21\xf1\xe0\x65\x32\x1a\x00\x37\x59\xd1\xe0\xf4\x6f\xf9\xae\x40\x5e\x6b\x49\xf5\xbf\x16\x2b\x5d\xfa\xf9\xfa"..., 256, 0) = 256
getrandom("\xb7\xd4\xa5\x73\xe2\x9f\x69\x53\x1f\x72\x43\x1b\x84\xa2\xd3\x47\xa3\xdd\x95\x00\x8d\xd1\x2d\x85\x27\x55\x5a\x39\xbb\x29\x45\x5a"..., 256, 0) = 256
getrandom("\x84\x4d\xcd\x68\x95\x42\x79\x1e\xd7\x0f\x75\xc3\xae\xcb\x85\xcc\xc0\xe8\xb4\xf4\x0b\xf4\x46\x7a\x94\xa7\x79\xc6\xd8\x3f\xc3\x79"..., 256, 0) = 256
getrandom("\x8f\x37\x67\x87\x35\x28\x0c\x3e\xda\x3d\xae\xa0\xd5\x2e\xb3\xa3\x26\x25\x92\x7d\x79\x9a\x01\xfa\x01\x14\xac\x1b\x63\x6f\x8f\x46"..., 256, 0) = 256
getrandom("\x07\xbe\xa7\xe6\x7d\x28\xe1\x82\x2a\x48\x56\xd4\x5b\xfc\x8f\x4d\x1c\x31\x9f\xac\xe0\x9c\x5c\x55\x39\xd0\x26\xe5\x7a\x7a\xca\xa9"..., 256, 0) = 256
getrandom("\x85\x54\xc8\x17\xff\x51\x74\x7c\x99\x82\x5c\x00\x1c\xda\xd3\x24\xee\x64\xb8\x4a\xa2\x37\x6c\xa0\x08\x1f\x36\x87\xa2\xdb\x4b\x06"..., 192, 0) = 192
linkat(AT_FDCWD, "/proc/self/fd/26", AT_FDCWD, "/tmp/qpdfview.zgSJJG.pdf", AT_SYMLINK_FOLLOW) = 0
openat(AT_FDCWD, "/tmp/qpdfview.zgSJJG.pdf", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 27
statx(27, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=STATX_ATTR_ENCRYPTED, stx_mode=S_IFREG|0600, stx_size=0, ...}) = 0
statx(AT_FDCWD, "/tmp/qpdfview.zgSJJG.pdf", AT_STATX_SYNC_AS_STAT|AT_SYMLINK_NOFOLLOW, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=STATX_ATTR_ENCRYPTED, stx_mode=S_IFREG|0600, stx_size=0, ...}) = 0
fstat(23, {st_mode=S_IFREG|0600, st_size=822188, ...}) = 0
pread64(23, "%PDF-1.6\r%\342\343\317\323\r\n510 0 obj\r<</Lin"..., 256, 0) = 256
pread64(23, "0>]/Index[510 20]/Info 509 0 R/L"..., 256, 256) = 256

[...]

pread64(23, "\r\nendstream\rendobj\r171 0 obj\r<</"..., 256, 821576) = 256
pread64(23, "h\336L\217Aj\3030\20E\2572\273H\213\310#\331J\342\22\2\301^tS0\270n6\331("..., 208, 821368) = 208
write(27, " "..., 3649) = 3649
close(27) = 0
openat(AT_FDCWD, "2241.pdf", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 27
statx(26, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=STATX_ATTR_ENCRYPTED, stx_mode=S_IFREG|0600, stx_size=0, ...}) = 0
read(26, "", 16384) = 0
statx(27, "", AT_STATX_SYNC_AS_STAT|AT_EMPTY_PATH, STATX_ALL, {stx_mask=STATX_ALL, stx_attributes=STATX_ATTR_ENCRYPTED, stx_mode=S_IFREG|0600, stx_size=0, ...}) = 0
close(27) = 0
lseek(26, 0, SEEK_SET) = 0
close(26) = 0
unlinkat(AT_FDCWD, "/tmp/qpdfview.zgSJJG.pdf", 0) = 0

as far as I can see which matches this part of the code

// Save document to temporary file...
QTemporaryFile temporaryFile;

adjustFileTemplateSuffix(temporaryFile, QFileInfo(filePath).suffix());

if(!temporaryFile.open())
{
    return false;
}

temporaryFile.close();

if(!m_document->save(temporaryFile.fileName(), withChanges))
{
    return false;
}

// Copy from temporary file to actual file...
QFile file(filePath);

if(!temporaryFile.open())
{
    return false;
}

if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
    return false;
}

if(!copyFile(temporaryFile, file))
{
    return false;
}

So file descriptor 26 is temporaryFile created using open("/tmp", O_TMPFILE) which is then made persistent at "/tmp/qpdfview.zgSJJG.pdf" using linkat.

This path is then opened by Poppler as file descriptor 27 to write out the modified document with the original document already open as file descriptor 23 and used to source most of then content. After this is done, the temporary file is closed by Poppler and qpdfview opens the original file which re-uses file descriptor 27.

Finally, copyFile tries to fill a 16 kB buffer from file descriptor 26 using

read(26, "", 16384) = 0

which does not yield any data. (Closing and re-opening temporaryFile seems to be a no-op in the used version of Qt.)

One thing I could imagine is that the file descriptor 26 is positioned at the end of the file instead of staying at the beginning for some reason specific to the underlying file system. (I am not sure whether it is specified how the file offset changes when the underlying file is appended via another file descriptor.)

I could try out a patch that just rewinds that file descriptor. Would you be able to test such a patch?

Regards,
Adam