Troubleshooters.Com and Linux Library present:
Fix: GUI Windows Won't Open
Copyright 2025 by Steve Litt, all rights reserved.
See the Troubleshooters.Com Bookstore.
This "cannot open any more GUI windows" symptom is often accompanied by the error message "Maximum number of clients reached", which can be viewed on the terminal on which you tried to run the program whose window won't open. This document is about inability to open windows, accompanied by the error message, assuming the error message is there for you to see.
The maximum number of clients is surprisingly low: In the hundreds or low thousands. Given that many programs, such as Chromium, use tens of clients, it doesn't take much to use up all your clients. However, if you need Chromium (or Google Chrome), you need it. Firefox and the rest of the browsers all have their own problems, either incompatiblity, bloatitude, or both. So you have one of two choices:
The usual cause is a few defective or overbloated applications that are hogging too many clients, making it impossible to run all the necessary applications. On my computer, these applications are:
reminders.py
: A badly written, zombie creating program written by me.chromium
, Chrome based browsers, and some other browsers.dbus-daemon
: An overcomplexificated client-shedding mess.sakura
: An otherwise great terminal program that runs three clients for every window it opens. Luckily, opening a tab on an existing Sakura window produces no additional clients.Here's how I fixed my particular situation:
reminder.py
: The bug is too subtle for me to find in a reasonable amount of time, so I eliminated the symptom by placing a command in my menu system, right next to the command that runs reminder.py
, to use the killall
and pkill
commands to kill every instance of this defective program.chromium
is very necessary to my workflow in situations requiring a full featured browser, so I do housekeeping early and often to eliminate Chromium tabs and windows no longer needed. I also use lesser browsers for lesser tasks.dbus-daemon
instance grabs 35 clients at start, and gradually accumulates more. So from time to time I use my init system to bring it back down to 35:sv restart dbus
.sakura
, I try very hard to use only one Sakura instance, with as many tabs as I need. This keeps client usage down to 3.Your first job is to acquire and observe the symptom. On a terminal already running, run another small GUI program, and if that program's window doesn't appear, scan the output on the terminal for "Maximum number of clients reached". If you see that string, you're dealing with this problem. Next step is to get a rough estimate of its magnitude with the following command:
lsof -U | wc -l
The preceding gives you the number of open Unix sockets. Observe that it varies according to which user issues it: User root
yields a higher number. I don't know which user gives the more indicative number, but for now I'm using the user who encountered the symptom, which in my case is user slitt
.
Note:
"Unix sockets" and what X calls "clients" are related. I'm not sure how they're related, but my subjective findings have been that as Unix sockets increase, so do window-stopping "clients".
Next is an 87 line Python program to get an idea of which programs and processes are hogging the most Unix sockets. It's actually two reports. The first breaks down only by executable name, sorted by number of sockets used. The grand total is on top, on the report's title line.
The second report is similar, except broken down by PID, so if necessary you can find which instance of a program is creating too many clients. The source of this program, whose name is lsof_anal.py
, follows:
#!/usr/bin/python import sys import subprocess import re def get_sock_list(): with subprocess.Popen( ["/usr/bin/lsof", "-U"], stdout=subprocess.PIPE, text=True ) as proc: lines = proc.stdout.readlines() return_lines = [] lineno = 0 for line in lines: if lineno > 0: fields = line.split() return_lines.append( '{} {}'.format( fields[0].ljust(10, ' '), fields[1].rjust(5, '0') ) ) lineno += 1 return return_lines def make_report_lines(lines): prevline = " " occurrences = 0 total_occurrences = 0 firstime = True report_lines = [] for line in lines: if firstime: firstime = False continue if line != prevline: st=str(occurrences).rjust(7, ' ') st += " " st += prevline report_lines.append(st) prevline = line occurrences = 1 if line == prevline: occurrences += 1 total_occurrences += 1 st=" {} GRAND TOTAL" st=st.format(str(total_occurrences)) report_lines.append(st) return sorted(report_lines,reverse=True) def remove_pids(lines): ss=0 for line in lines: fields = line.split(' ', 1) lines[ss] = fields[0] ss += 1 return lines def print_array(arr): for line in arr: print(line) def main(): socklist = [] socklist = get_sock_list() socklist = sorted(socklist) by_program_and_pid = \ make_report_lines(socklist) socklist = remove_pids(socklist) socklist = sorted(socklist) by_program = \ make_report_lines(socklist) print("BY PROGRAM REPORT:", end='') print_array(by_program) print("\n\n\n") print("BY PROGRAM AND PID REPORT: ", end='') print_array(by_program_and_pid) if __name__ == '__main__': main()
On my computer a few minutes ago, the preceding program output the following:
[slitt@mydesk lsof_anal]$ ./lsof_anal.py
BY PROGRAM REPORT: 181 GRAND TOTAL
80 chromium
38 dbus-daem
10 gvim.warn
8 xterm
7 claws-mai
5 lxtermina
5 bluefish
4 mpv
4 gnome-key
4 chrome_cr
4 at-spi2-r
3 xdg-docum
3 xdg-deskt
3 dunst
3 dbus-laun
2 xinit
2 xdg-permi
2 parcellit
2 openbox
2 gvfsd-fus
2 gvfsd
2 goa-ident
2 goa-daemo
2 fetchmail
2 dconf-ser
0
BY PROGRAM AND PID REPORT: 181 GRAND TOTAL
27 dbus-daem 01541
24 chromium 17543
13 chromium 17755
12 dbus-daem 01612
7 claws-mai 09275
7 chromium 17836
7 chromium 00708
6 chromium 17595
6 chromium 17584
5 lxtermina 14701
5 chromium 28776
5 chromium 10911
5 chromium 00396
5 chromium 00312
5 bluefish 11512
4 gvim.warn 23967
4 gvim.warn 09885
4 gvim.warn 03695
4 gnome-key 25872
4 at-spi2-r 01714
3 zeitgeist 13252
3 zeitgeist 01518
3 xdg-docum 01687
3 xdg-deskt 25864
3 dunst 01622
3 dbus-laun 01540
3 chromium 17554
3 chromium 17552
3 chromium 17551
3 chrome_cr 17545
2 xterm 22013
2 xterm 21028
2 xterm 20068
2 xterm 18360
2 xterm 03940
2 xterm 01885
2 xterm 00768
2 xinit 01401
2 xdg-permi 01692
2 parcellit 01521
2 openbox 01420
2 mpv 12150
2 mpv 08310
2 mpv 07460
2 gvfsd-fus 01638
2 gvfsd 01628
2 goa-ident 01674
2 goa-daemo 01666
2 fetchmail 03001
2 dconf-ser 07064
2 chrome_cr 17547
0
Use the output of the preceding to find out which programs are hogging clients, and which processes contribute to the hogging. While you're at it, now's a great time to find all zombie processes and kill them, or if you can't kill them, investigate and kill their parents. The following command shows all your zombies:
ps -ao stat,pid,ppid,command | grep -i ^z
Try killing them by their PID. If that doesn't work, investigate their PPID by grepping for it (the number right after the PID in the output of the preceding command). A great shellscript for investigating a ppid is the following:
#!/bin/ksh ps -ao pid,ppid,stat,command | head -n1 ps -ao pid,ppid,stat,command | grep "^$1"
Just use the PPID of the zombie as the argument for this shellscript.
As time goes by you'll find patterns and correlations to your inability to open new GUI windows. Whenever confronted with this symptom, run lsof_eval.py
, the Linux socket reporting program, to see patterns. What's the grand total of sockets reported by the program? Looking at the "by program" report, what programs seem to be opening the most Unix sockets? Check out the "by program and pid" report to see whether one particular process has a lot of Unix sockets open. Use the zombie finding shellscript described in the preceding section to find all zombies, and kill them if you can. Once you can open GUI windows again, recheck all these things to get an idea of the the number of open Unix sockets and other information contributing to inability to open further GUI windows.
As time goes by and you get familiar with the patterns, you might be able to make a cron triggered shellscript, or systemd timer triggered if you drive on that side of the road, to get rid of known pests like my known-bad reminders.py
, and perhaps warning you of other problems before creating windows becomes impossible.
Sometimes it becomes impossible to open further GUI Windows. Sometimes, if you try to run window-producing programs from a command prompt on a GUI terminal, you're greeted with a bunch of error messages including the dreaded "Maximum number of clients reached". When you see this error message, you know you're dealing with the problems discussed in this document.
The best way of handling this is to use the diagnostic shellscripts and Python programs described in this document, and perhaps others of your own making, to get familiar with the problem and keep it under control.