Detect whether wineserver is fully started? Signal? File?

Sebastian M. Ernst ernst at pleiszenburg.de
Fri Jun 16 16:06:35 CDT 2017


Hi Sebastian,

thanks a lot for the idea.

I tried to convert your idea into a quick & dirty piece of actual code
for testing it - see below this email. Simplified into pseudo-code I do
the following:
- create socket object, type unix / stream (w/o reference to file/path)
- try: connect to socket file
- if failed, wait for x seconds and repeat last step (until timeout)
- if succeeded, close the connection and let the code go ahead

It will result in a log like the following (assuming that most involved
files are cached in RAM, otherwise the numbers in the "appeared" message
will be somewhat higher):

[wine session] Launching wineserver ...
[wine session] ... started with PID 28549 ...
[wine session] ... expecting socket at
/tmp/.wine-1000/server-803-690008/socket ...
[wine session] ... appeared (after 0.00 seconds & 1 attempts)!

So far so good. This code works *sometimes* (rarely, however). It will
always tell me that the desired socket appeared, which it actually does,
but usually, most of the time, any subsequent command like "wine
some.exe" or "winepath -w /path" following the launch of my wineserver
will crash with this error:
"wine client error:0: recvmsg: Connection reset by peer"

It seems that my attempt to connect to the socket (and disconnect from
it if the connection succeeds) renders it unusable for any wine process
trying to connect to it afterward. Just leaving my connection open does
not change the result. What I am missing or doing wrong? Am I using the
right type of socket (stream)? Is there some sort of a simple "ping"
message/signal I can send to the wineserver through the socket which
should result in a deterministic answer I can use for validating the
connection?

Regards,
Sebastian



# Status log
self.log.out('[wine session] Launching wineserver ...')

# Start wine server into prepared environment
self.proc_wineserver = subprocess.Popen(
	['wineserver', '-f', '-p'], # run persistent in foreground
	stdin = subprocess.PIPE,
	stdout = subprocess.PIPE,
	stderr = subprocess.PIPE,
	shell = False
	)

# Status log
self.log.out('[wine session] ... started with PID %d ...' %
self.proc_wineserver.pid)

# Get info on WINEPREFIX folder
info_wineprefix = os.stat(self.dir_wineprefix)

# Get path of wineserver socket file
socket_path = os.path.join(
	tempfile.gettempdir(),
	'.wine-%d' % os.getuid(),
	'server-%x-%x' % (info_wineprefix.st_dev, info_wineprefix.st_ino),
	'socket'
	)

# Status log
self.log.out('[wine session] ... expecting socket at %s ...' % socket_path)

# Create socket client
wineserver_client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# Set a timeout
wineserver_client.settimeout(1.0) # seconds
# Status variable
got_connection = False
# Time-step
wait_for_seconds = 0.01
# Timeout
timeout_after_seconds = 30.0
# Already waited for ...
started_waiting_at = time.time()
# Connection trys
tried_this_many_times = 0

# Run loop until socket appears
while True:

	# Does socket file exist?
	if os.path.exists(socket_path):

		# Count attempts
		tried_this_many_times += 1

		# Can I connect to it?
		try:
			wineserver_client.connect(socket_path)
			got_connection = True
			break
		except:
			pass

	# Break to loop after timeout
	if time.time() >= (started_waiting_at + timeout_after_seconds):
		break

	# Wait before trying again
	time.sleep(wait_for_seconds)

# Evaluate the result
if not got_connection:

	self.log.out(
		'[wine session] ... did not appear (after %0.2f seconds & %d
attempts)! Quit.' % (timeout_after_seconds, tried_this_many_times)
		)
	sys.exit()

else:

	# If it worked, disconnect
	wineserver_client.close()

	# Log status
	self.log.out(
		'[wine session] ... appeared (after %0.2f seconds & %d attempts)!' %
(time.time() - started_waiting_at, tried_this_many_times)
		)



Am 12.06.2017 um 20:43 schrieb Sebastian Lackner:
> 
> I would suggest to implement the same logic as used by Wine itself.
> Basically, you would write a loop which periodically tries to connect to the
> wineserver UNIX socket, until it finally succeeds. The socket will appear
> at the following location (pseudocode):
> 
> info = os.stat(WINEPREFIX)
> socket_path = os.path.join("/tmp", ".wine-%d" % os.getuid(), "server-%x-%x" % (info.st_dev, info.st_ino))
> 
> Best regards,
> Sebastian
> 



More information about the wine-devel mailing list