xclip does not terminate when tracing it
Asked Answered
B

2

8

I have made the following observations:

$ xclip text.txt

The execution terminates instantly, it copies the content of text.txt to the default selection XA_PRIMARY which means you can paste it through your middle mouse button or xclip -o.

When I want to see what xclip is doing, it does not terminate anymore:

$ xclip -verbose text.txt
Connected to X server.
Using UTF8_STRING.
Reading text.txt...
Waiting for selection requests, Control-C to quit
  Waiting for selection request number 1

It does not terminate until I select something in my X11 system, for instance this very output I have pasted here. I would understand this, if the behavior is limited to verbose. After all you want to sit around and see what happens.

I can reproduce the same behavior with strace, but only if the fork option is provided

$ strace -f xclip text.txt

or when shelling out from Ruby with a system execution command that should return the output, which is in fact nothing.

$ ruby -e "`xclip text.txt`"

The hints that strace gave, is that it is polling on a file descriptor to wait for an event. This event is satisfied if I select something. Is this behavior explainable? I have gotten evidence, that this is not reproducable on any system. Could this be related to the ticket #9 Not closing stdout when setting clipboard from stdin?

I am running xclip version 0.12 on Ubuntu 13.04.

Bushey answered 8/10, 2013 at 17:13 Comment(0)
L
10

XClip forks a child when launched without -verbose. The only difference with -verbose is that there is no child forked and the same original process handles ConvertSelection events.

Usually in X Window toolkits copy/paste is implemented via X Selections:

Selections are global server resources named by an atom and owned by a particular client. The number of selections is not limited by the protocol; as many selections as atoms may exist. Selections are designed to provide the basis for building communication mechanisms between clients. The official definition is found in the glosary of the X Protocol:

"...an indirect property with dynamic type; that is, rather than having the property stored in the server, it is maintained by some client (the ‘‘owner’’). A selection is global in nature and is thought of as belonging to the user (although maintained by clients), rather than as being private to a particular window subhierarchy or a particular set of clients."

From the applications perspective, selections provide a mechanism for transmitting information between X clients. As X is a networking protocol, the existance of a separate channel for data transmission between the various clients cannot be assumed to exist. Selections are intended only for data transfer which directly relates the the user-interface aspects of the application, although there isn’t any enforcement of this policy.

Content of selection is stored in application itself and requested with ConvertSelection event ("convert" here because there is a way for client to ask for particular mimetype (or "view", or format) of selected data. Conversion, again, happens in the application which owns selected buffer.

Because of this architecture, there is no way to "copy text to system buffer and exit" - because you are a system buffer. XClip simulates "copy and exit" by forking and daemonizing.

Lubricity answered 8/10, 2013 at 23:27 Comment(6)
Could you elaborate that on what I have observed through strace and shelling out from another program? Probably this would make it clearer , because so far I don't see what this has to do with forking, besides that it does not work in a non-concurrent way?Bushey
I guess shell in ruby waits for process tree to terminate (including forked child). If you do xclip test.txt in another shell your ruby process will exit because xclip child loses X Selection and does not need to serve it anymoreLubricity
I don't know why this answer is negatively rated. It's absolutely correct. -verbose disables the daemonizing behavior of xclip. When you strace -f a daemonizing program, the strace doesn't get magically daemonized too, it just stays in the foreground, tracing all descendants of the original program until there are none left. About ruby I can't say much since I've never used it, but if the backquotes in the ruby program are like backquotes in shell or perl, then it could indeed be waiting for the daemonized process to write to the pipe that it still has open on stdout.Softhearted
@WumpusQ.Wumbley Thanks for your comment, putting it into the context of daemonization made it a lot clearer.Bushey
@AndreySidorov Would you mind adding Wumpus additions to your answer? :)Bushey
I added text on X selections - will also research a bit how ruby backticks handles daemonized processesLubricity
L
3

As explained by the accepted answer which did not solve the problem... Data which is "copied" to the clipboard is never copied to the clipboard. Instead, the clipboard records a reference to the process which is expected produce information that is pretending to be copied to the clipboard. In this way, the clipboard is designed to handle possibly large amounts of complex information which might be presented in many different ways. One might think an exception for simple text would be made, but there are no exceptions.

Therefore, the program which "copied" the information to the clipboard needs to keep running until the contents of the clipboard are replaced by another executable. If the processes which "copied" information to the clipboard ends, then the contents of the clipboard are lost.

xclip immediately reads the data then deamonizes itself into the background to wait to serve it when requested which xclip calls "Waiting for selection request" as it counts the paste requests.

xclip -selection clipboard <(echo -n 'test')

the above works beauitfully while

x=`echo -n hi-; xclip -selection clipboard <(printf '%s' 'test'); echo there`

assigns 'hi-there' to x, but never returns because bash awaits xclip to write something to stdout which will never happen. The xclip process will belong to the bash group, but $(bash...) does not reassign /proc/$$/fd/1, so I don't know how to easily test for it. But...

x=`echo -n hi-; 1>/dev/null xclip -selection clipboard <(echo -n 'test'); echo you`

returns without waiting for xclip to end because bash knows that any possible output from xclip will never produce output for it because xclip's stdout has been reassigned elsewhere.

Problem Solved!

Linette answered 22/9, 2023 at 4:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.