After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 539312 - paste of large buffers often fails
paste of large buffers often fails
Status: RESOLVED NOTGNOME
Product: vte
Classification: Core
Component: general
0.16.x
Other All
: Normal normal
: ---
Assigned To: VTE Maintainers
VTE Maintainers
Depends on:
Blocks:
 
 
Reported: 2008-06-20 16:04 UTC by Pierre Ossman
Modified: 2013-09-18 13:34 UTC
See Also:
GNOME target: ---
GNOME version: 2.23/2.24


Attachments
test data (3.96 KB, message/rfc822)
2008-06-20 16:14 UTC, Pierre Ossman
Details

Description Pierre Ossman 2008-06-20 16:04:58 UTC
Please describe the problem:
This is a bug that has been present since forever, I just haven't really gotten around to reporting it. Oddly enough, noone else has either. :)

The problem is that vte seems to mishandle INCR. Pasting large buffers often results in just part of the data getting to the application. Might be a clipboard protocol issue, or a buffer handling problem where it floods stdin of the application. I don't really know how to determine which of those it is. Protocol issue is my best guess though as it stops on the same byte each time it fails.

The problem does not seem to be with the clipboard source as retrying the paste multiple times eventually gets it working. Also, pasting into another application (e.g. gedit) works just fine.

Steps to reproduce:


Actual results:


Expected results:


Does this happen every time?
No, but often (provided the buffer is large enough).

Other information:
Comment 1 Pierre Ossman 2008-06-20 16:12:56 UTC
Odd... I played around a bit more with this in an effort to provide more info, and I noticed that for at least one test case, the problem is with the display, not the actual paste. I.e. more data gets sent to the application than is echoed to the screen.
Comment 2 Pierre Ossman 2008-06-20 16:14:16 UTC
Created attachment 113125 [details]
test data

This is one example of the data I've been trying to paste. This command easily provokes it here:

cat - > foo
Comment 3 Behdad Esfahbod 2008-06-20 17:21:49 UTC
Reproduced.
Comment 4 Behdad Esfahbod 2008-08-14 06:34:56 UTC
Humm, for no apparent reason I can't reproduce this anymore.
Comment 5 Pierre Ossman 2008-08-19 06:28:35 UTC
Odd, me neither.
Comment 6 Pierre Ossman 2008-08-31 18:18:04 UTC
It's baaaack!

vte-0.17.2-1.fc10.i386
Comment 7 Chris Wilson 2008-09-01 11:19:57 UTC
My suspicion is that this is related to bug 538344. Could you try with HEAD or with the patch applied from that bug?
Comment 8 David Woodhouse 2013-09-12 19:51:20 UTC
This is happening again in Fedora 19 (vte 0.28.2, gnome-terminal 3.8.4).

Select more than 4KiB of text from anywhere, attempt to paste it into gnome-terminal and only the first 4KiB shows up.

I've *also* seen the purely cosmetic version of the bug in the past, where you 'cat > file' and paste, and it *looks* like the paste is truncated but the contents of the file are correct. That's not what's happening now. This time the paste really *is* truncated at 4KiB.
Comment 9 David Woodhouse 2013-09-13 21:34:13 UTC
Hm, strange.

If I paste a *very* large chunk of a C file from an emacs buffer, it works but with the cosmetic issue as described. Only the first 4KiB shows up, I hit enter and Ctrl-D to terminate my 'cat > file', and the rest of the paste shows up as soon as I hit enter.

If I paste a large chunk of XML from firefox (actually the long line from https://bugzilla.gnome.org/show_bug.cgi?id=707655#c0 ) it's truncated at 4KiB.

If I paste that same XML into emacs from firefox it arrives OK. If I paste it into gnome-terminal from emacs and it's also truncated at 4KiB.

And if I format it so that it isn't one big line, it also arrives OK in gnome-terminal.
Comment 10 Behdad Esfahbod 2013-09-13 22:02:37 UTC
Ok, we should add printf debugging to vte to see where exactly it's being lost...  I'll try to take a look, though if Egmont wants to look, he should go for it ;).
Comment 11 David Woodhouse 2013-09-13 22:30:32 UTC
[dwmw2@shinybook src]$ VTE_DEBUG=selection ./vte2_90 
Fork succeeded, PID 12982
Pasting PRIMARY.
Requesting clipboard contents.
Pasting 18579 UTF-8 bytes.


Strace looks like this (fd 7 is /dev/ptmx)...

13354 write(2, "Pasting 18579 UTF-8 bytes.\n", 27) = 27
13354 mmap(NULL, 135168, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fee28bfe000
13354 write(7, "> <SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsd=\"http://www"..., 18579) = 18579
13354 poll([{fd=6, events=POLLIN|POLLOUT}], 1, 4294967295) = 1 ([{fd=6, revents=POLLOUT}])
13354 writev(6, [{"\23\0\3\0N\0\240\2\\\1\0\0", 12}, {NULL, 0}, {"", 0}], 3) = 12
13354 recvfrom(6, "\34\0\231\2N\0\240\2\\\1\0\0Q(&-\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 4096, 0, NULL, NULL) = 32
13354 recvfrom(6, 0x2150ca4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
13354 poll([{fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=3, events=POLLIN}], 3, 0) = 0 (Timeout)
13354 recvfrom(6, 0x2150ca4, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
13354 poll([{fd=5, events=POLLIN}, {fd=6, events=POLLIN}, {fd=3, events=POLLIN}, {fd=7, events=POLLIN}], 4, 293) = 1 ([{fd=7, revents=POLLIN}])
13354 write(5, "\1\0\0\0\0\0\0\0", 8)   = 8
13354 read(7, "> <SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:xsd=\"http://www"..., 8176) = 4095
13354 read(7, "\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7\7"..., 4081) = 3708
13354 read(7, 0x23b17a7, 373)           = -1 EAGAIN (Resource temporarily unavailable)


Now wtf happened there? We *got* the 18579 bytes just fine from the clipboard, and we wrote them to the PTY master. And then we got some of them back. And a lot of BELs? 

FWIW if I strace the 'cat' I'm doing within the terminal, it sees this:

read(0, "> <SOAP-ENV:Envelope xmlns:SOAP-"..., 65536) = 4096
write(1, "> <SOAP-ENV:Envelope xmlns:SOAP-"..., 4096) = 4096


Now I'm suspecting a kernel bug...?
Comment 12 David Woodhouse 2013-09-13 23:01:27 UTC
Simple test case:

#define _GNU_SOURCE
#define _XOPEN_SOURCE
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

char buf[16384];

int main(void)
{
	int mfd, cfd;

	memset(buf, 0x5a, sizeof(buf));
	buf[16383]='\n';
	mfd = getpt();
	unlockpt(mfd);
	grantpt(mfd);
	cfd = open(ptsname(mfd), O_RDWR|O_NOCTTY|O_NONBLOCK);
	write(mfd, buf, 16384);
	read(cfd, buf, 16384);
	read(cfd, buf, 16384);
}

open("/dev/pts/5", O_RDWR|O_NOCTTY|O_NONBLOCK) = 4
write(3, "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"..., 16384) = 16384
read(4, "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"..., 16384) = 4096
read(4, 0x6010a0, 16384)                = -1 EAGAIN (Resource temporarily unavailable)
exit_group(-1)                          = ?


Kernel ate my buffer.
Comment 13 Behdad Esfahbod 2013-09-13 23:45:05 UTC
Umm.  Can you repro with other terminals too?
Comment 14 Behdad Esfahbod 2013-09-13 23:45:32 UTC
Also, you planning to followup somewhere else?  A closed bug is no good for tracking.  Thanks for debugging BTW.
Comment 15 Egmont Koblinger 2013-09-14 10:11:43 UTC
Behdad, you're reading my mind :) This is the second item on my personal bugfixing todo list (apart from rewrapping on resize). Unfortunately I can't promise any timeline when I'd be able to work on this, nor can I promise that I'd be able to fix it.

It's a kernel bug (surprisingly MacOS kernel being buggy too). I reported it to kernel developers a while ago: https://lkml.org/lkml/2012/2/15/328 , but I failed to convince them it was a kernel bug. Maybe you could help me convince them and get it fixed.

Luckily it's very easily reproducible on usermode linux, so it only takes a few seconds to recompile and test any attempt and get any debug info, without actually rebooting the box. The tough part IMO is to get to understand the kernel's code.
Comment 16 David Woodhouse 2013-09-14 20:35:35 UTC
It's having the tty in icanon mode which does it. Canonical mode is line-editing mode, as opposed to non-canonical mode where the input is simply passed through directly.

http://pubs.opengroup.org/onlinepubs/009604599/basedefs/xbd_chap11.html#tag_11_01_06

The kernel has a 4KiB buffer for the line editing, and when it receives more than 4096 characters it'll just beep unhappily at you and drop them.
Hence all those \7 (BEL) characters in what we read back from the pty master, in the strace in comment 11.

Interestingly, fpathconf(cfd, _PC_MAX_CANON) is returning 255, not 4096.

I'd certainly be open to expanding the buffer, but it's non-swappable kernel memory. It's a very non-trivial task to do it in a way that doesn't open the system to rampant denial of service attacks.
Comment 17 David Woodhouse 2013-09-14 21:01:22 UTC
Looking at your ptmx3.c test case in that bug, I think we're experiencing something different. My issue is simply that I am overflowing the line buffer with a line that is too big. You are probably experiencing some issues with switching to/from icanon mode, not consistently flushing that buffer when we *exit* icanon mode or something like that?
Comment 18 Egmont Koblinger 2013-09-15 22:53:10 UTC
We're experiencing something little bit different, but the main point is the same.

How much do you know about the termios flags, especially the flow control stuff? And about the kernel's internals?

The big question I think is: what is the desired behavior? In my opinion, expanding the buffer is not the way to go. No matter what the buffer size is, I think things should always work perfectly, without any data being corrupted / dropped / replaced by bell. If the kernel's buffer is full, it should report a short write or a non-writable state towards VTE, exactly as if it'd do for a pipe. Or, at least there should be a combination of all those termios flags (and still be able to switch back-n-forth between raw and cooked) where this is the behavior.

It should be vte's responsibility (and IIRC it does it correctly) to continue feeding the paste data into the kernel, while still processing the data printed by the application to make sure there's no deadlock between the two.
Comment 19 David Woodhouse 2013-09-18 11:18:33 UTC
(In reply to comment #18)
> We're experiencing something little bit different, but the main point is the
> same.

I don't know about that. Your case does seem to be a kernel bug. I'm not sure about mine.

> How much do you know about the termios flags, especially the flow control
> stuff? And about the kernel's internals?
> 
> The big question I think is: what is the desired behavior? In my opinion,
> expanding the buffer is not the way to go. No matter what the buffer size is, I
> think things should always work perfectly, without any data being corrupted /
> dropped / replaced by bell. If the kernel's buffer is full, it should report a
> short write or a non-writable state towards VTE, exactly as if it'd do for a
> pipe.

And then what? If the slave is in canonical (line-editing) mode, and we have a 4KiB buffer, there is *nothing* you can do to send a line that is more than 4KiB in size. It just can't be done. There is nothing that anything in userspace can do (apart from switching the slave to non-canonical mode, of course) to allow a line more than 4KiB to get through.

> It should be vte's responsibility (and IIRC it does it correctly) to continue
> feeding the paste data into the kernel, while still processing the data 
> printed by the application to make sure there's no deadlock between the two.

But the application won't *receive* the line until the newline at the end of it is sent. It's not simply a case of vte waiting for the buffer to clear — the contents of the buffer *can't* be sent to the slave until the line is complete, and we can't write extra data to complete the line because there's not enough room in the buffer for it...
Comment 20 Egmont Koblinger 2013-09-18 13:32:13 UTC
Okay, I understand your point, you're right. Indeed, if the slave is in canonical (line-editing) mode (such as a "cat" command), and you paste >4kiB data, and that data has no '\n' character inside, there's not much you can do to prevent dropping bytes.

(Note: if you're typing from keyboard, pressing ^D will cause that partial line to get delivered to the application without a trailing newline. Maybe vte could simulate the same after every 4kB? It'd be a nasty workaround, probably with other side effects, not sure if it's worth it.)

However, this is not what the original bugreport was about. The example data there is a "nice" text file (lines of ~100 characters), and pasting that should work perfectly.
Comment 21 David Woodhouse 2013-09-18 13:34:24 UTC
OK, that's your kernel bug for which you have a test case. I'll look into that further when I get home from Linuxcon/Plumbers conf.