Sublime Forum

Subprocess freezes when I ask for xclip output

#1

Arch Linux 4.16.13, Sublime 3176, xclip 0.13

Hi, I have problem with getting output from xclip commands.

  • Only from xclip
  • Only when I try to receive output of command
  • All problems appears only when I run my python code from sublime plugin

Here is simple plugin setup:

import sublime
import sublime_plugin

from pprint import pprint

class ClipTargets(sublime_plugin.WindowCommand):
	def run(self):
		cmd = "xclip -o -sel c -t TARGETS"

		r = subprocess.check_output(cmd,
			shell=True,
			universal_newlines=True,
			timeout=1
		)
		pprint(r)
		
		# I'm trying check_output OR Popen.communicate - same problem
		# p = subprocess.Popen(cmd,
		# 	stdout=subprocess.PIPE,
		# 	stdin=subprocess.PIPE,
		# 	shell=True
		# )

		# stdout, stderr = p.communicate(timeout=1)
		# pprint(stdout)

In this command I’m try to receive clipboard targets list from current selection. This command is freezes(TimeoutExpired) if I run it when sublime is a clipboard content owner(if last text was copied in sublime). More simpler command xclip -o -sel c behaves the same way. But I need not just text from clipboard so any sublime or python commands for working with clipboard isn’t suit.
If last copying was performed in any other app, then I receive my targets list.

Why is this happening? How I can bypass this problem? Can I detect that sublime is clipboard content owner before running xclip command?

0 Likes

#2

I was write my c++ gtk clipboard client, that check clipboard targets like xclip. But it acts like xclip!
When I ask for clipboard targets from external process - it works.
When I ask for clipboard targets from sublimes subproces result return only if clipboard content belongs to non-sublime.

I was try threading.Thread - it freezes too.
sublime.set_timeout_async works for me and xclip/my program show result in sublime console…BUT! It runs AFTER main process ends. This doesn’t looks like ‘async’. Here is example:



def test():
	cmd = "xclip -o -sel c -t TARGETS"
	cmd = "/home/hxss/cliptargets --check"

	r = subprocess.check_output(cmd,
		shell=True,
		universal_newlines=True,
		timeout=1
	)
	return r

state = None
def test2():
	r = None
	pprint('test2: 0')
	r = test()
	pprint('test2: ' + r)
	return r

class ClipTargets(sublime_plugin.WindowCommand):
	def run(self):
		pprint('run: 0')
		r = 1


		# t = threading.Thread(target=test2)
		# t.run()
		sublime.set_timeout_async(test2, 0)

		i = 0
		while state is None and i < 2:
			pprint('i: ' + str(i))
			i += 1
			time.sleep(1)

		pprint('run: ' + str(r))

it shows:

'run: 0'
'i: 0'
'i: 1'
'run: 1'
'test2: 0'
'test2: 1\n' //this result of 'cliptargets --check' command

As you see test methods calls AFTER loop in main thread. So where is async actions?
How I can receive answer from subprocess/subthread in my run method? And why asking for sublime clipboard targets from sublime subprocess freeze all application?

0 Likes

#3

I didn’t take a close look at your issue, but the first guess would be that the xclip call is blocking and you executing (and waiting for) that on the main thread will cause the ui to freeze.

Using a separate thread shouldn’t cause a freeze, however.

0 Likes

#4

My second message is devoted to experiments with threads.
I can run new thread with needed my class method and start waiting loop in main thread that would be stoped when method in new thread complete the task. e.g.:


class ClipTargets(sublime_plugin.WindowCommand):
	state = None

	def run(self):
		self.state = None
		pprint('run: 0')

		pprint('threads: ' + str(threading.active_count()))

		t = threading.Thread(target=self.test2)
		t.start()

		pprint('threads: ' + str(threading.active_count()))

		i = 0
		while self.state is None and i < 10:
			pprint('i: ' + str(i))
			i += 1
			time.sleep(0.2)

		pprint('run: ' + str(self.state))

	def test2(self):
		time.sleep(0.3)
		self.state = 1

It works. The loop stops after 2 iterations.
But if I run subprocess.check_output in new thread - it return timeout error.

0 Likes