Last active
January 8, 2022 17:44
-
-
Save ssokolow/9833321 to your computer and use it in GitHub Desktop.
"wineserver -k" wrapper which kills every WINEPREFIX the user has running (Very useful for killing misbehaving games in PlayOnLinux)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
`wineserver -k` wrapper which kills every WINEPREFIX the user has running | |
(Very useful for killing misbehaving games in PlayOnLinux) | |
Known Bugs: | |
- The script will miss wineserver instances where the WINESERVER environment | |
variable was used to specify a wineserver binary not named "wineserver" | |
""" | |
__appname__ = "Blanket Wineserver Killer for Linux" | |
__author__ = "Stephan Sokolow (deitarion/SSokolow)" | |
__version__ = "0.2" | |
__license__ = "MIT" | |
import glob, os, subprocess, sys | |
def parse_procfile(path): | |
"""Parse a file containing a null-separated text list or return []. | |
NOTE: Strips blank fields. | |
""" | |
try: | |
with file(path) as fh: | |
return [x for x in fh.read().split('\0') if x.strip()] | |
except: | |
return [] | |
def pfind(command): | |
"""Return PIDs where argv[0] ends with the given string. | |
(Reinvent part of pgrep so we don't have it as an external dependency.) | |
""" | |
pids = [] | |
for path in glob.glob('/proc/*/cmdline'): | |
cmd = parse_procfile(path) | |
if cmd and cmd[0].endswith(command): | |
pid = os.path.split(os.path.split(path)[0])[1] | |
try: | |
pids.append(int(pid, 10)) | |
except ValueError: # Catch failed int() conversions | |
print "ERROR: Skipping invalid PID: %s" % pid | |
continue | |
return pids | |
def env_for(pid): | |
"""Retrieve the environment for a PID or return [].""" | |
env = parse_procfile('/proc/%d/environ' % pid) | |
if env: # If we managed to retrieve the environment, parse it | |
env = dict(x.split('=', 1) for x in env if '=' in x) | |
return env | |
if __name__ == '__main__': | |
# Query the list of running wineserver instances | |
pids = pfind('wineserver') | |
if pids: | |
print "Found PIDs: %s" % ' '.join(str(x) for x in pids) | |
else: | |
print "No wineserver instances found" | |
sys.exit(1) | |
# Resolve PIDs to WINEPREFIX values | |
environs = {} | |
for pid in pids: | |
# Retrieve the environment for the process | |
env = env_for(pid) | |
if env is None: | |
print "WARNING: Skipping wineserver we can't kill: %d" % pid | |
continue | |
# Store the environments, indexed by WINEPREFIX | |
fallback_prefix = os.path.join(env.get('HOME', '~'), '.wine') | |
prefix = env.get('WINEPREFIX', fallback_prefix) | |
environs[prefix] = env # deduplicate | |
print "Found prefixes:\n\t%s" % '\n\t'.join(environs.keys()) | |
# Actually kill them | |
print "Killing processes:" | |
for prefix, env in environs.items(): | |
print "\t%s" % prefix | |
subprocess.call(['wineserver', '-k'], env=env) | |
print "Done." | |
#TODO: Research how to query the default monitor resolution so we can call | |
# xrandr in a non-site-specific manner. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment