rlk@THINK.COM (Robert L Krawitz) (03/22/90)
VERSION:
R4
CLIENT MACHINE and OPERATING SYSTEM:
Sun 4/60 running SunOs 4.0.3 (irrelevant)
DISPLAY TYPE:
BW (probably irrelevant)
WINDOW MANAGER:
twm (but not important)
AREA:
Xsun
SYNOPSIS:
Setting the root window pixmap causes a memory leak.
[2(rlk)||{!38}<underprize.think.com>/tmp_mnt/am/src.new/X11/R4/X11R4/fixes]
% ps ux
USER PID %CPU %MEM SZ RSS TT STAT START TIME COMMAND
...
rlk 472 0.0 5.964612 896 co S 09:39 31:51 /usr/bin/X11/Xsun :0 -a
...
I was doing nothing else out of the ordinary.
DESCRIPTION:
I have a program that attempts to display a "rotor" on the root window:
a sequence of bitmaps that when displayed in sequence appear to move in
a rotational pattern on the screen. I use six bitmaps, each 32x32
pixels. I left the program running for about 2 hours, at 20
updates/second (thus doing between 70,000 and 100,000 updates).
The inner loop, cribbed (and slightly modified from) xsetroot, looks
like this:
/*
* SetBackgroundToBitmap: Set the root window background to a caller supplied
* bitmap.
*/
SetBackgroundToBitmap(bitmap, width, height)
Pixmap bitmap;
unsigned int width, height;
{
Pixmap pix;
GC gc;
XGCValues gc_init;
gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen));
gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen));
if (reverse) {
unsigned long temp=gc_init.foreground;
gc_init.foreground=gc_init.background;
gc_init.background=temp;
}
gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init);
XSetWindowBackgroundPixmap(dpy, root, bitmap);
XFreeGC(dpy, gc);
XClearWindow(dpy, root);
XFlush(dpy);
unsave_past = 1;
}
(Never mind that the code looks highly sub-optimal on first glance; I
just hacked at the code until it worked, because I haven't programmed X
in maybe 3 years in the X10 days; I also put no effort into the user
interface).
REPEAT BY:
Run program below.
SAMPLE FIX:
None.
****************************************************************
/* Copyright 1987, Massachusetts Institute of Technology */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include "X11/bitmaps/gray"
/*
* xsetroot.c MIT Project Athena, X Window system root window
* parameter setting utility. This program will set
* various parameters of the X root window.
*
* Author: Mark Lillibridge, MIT Project Athena
* 11-Jun-87
*/
char *index();
#define Dynamic 1
char *program_name;
Display *dpy;
int screen;
Window root;
char *fore_color = NULL;
char *back_color = NULL;
int reverse = 0;
int save_colors = 0;
int unsave_past = 0;
Pixmap save_pixmap = (Pixmap)None;
Pixmap ReadBitmapFile();
unsigned long NameToPixel();
main(argc, argv)
int argc;
char **argv;
{
int excl = 0;
int nonexcl = 0;
int restore_defaults = 0;
char *display_name = NULL;
char *name = NULL;
char *cursor_file = NULL;
char *cursor_mask = NULL;
char *cursor_name = NULL;
char *solid_color = NULL;
Cursor cursor;
int gray = 0;
char *bitmap_file = NULL;
int mod_x = 0;
int mod_y = 0;
register int i;
unsigned int time = 100000;
unsigned int *ww, *hh;
Pixmap *bitmap;
program_name=argv[0];
argv++;
argc--;
for (i=0; i<argc; i++)
{
if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i]))
{
if (++i>=argc) exit(1);
display_name = argv[i];
}
else if (!strcmp ("-time", argv[i]) || !strcmp("-t", argv[i]))
{
if (++i>=argc) exit(1);
time = (unsigned) atoi(argv[i]);
}
else
{
argc -= i;
argv += i;
break;
}
}
bitmap = (Pixmap *) calloc(argc, sizeof(Pixmap));
hh = (unsigned *) calloc(argc, sizeof(unsigned));
ww = (unsigned *) calloc(argc, sizeof(unsigned));
dpy = XOpenDisplay(display_name);
if (!dpy) {
fprintf(stderr, "%s: unable to open display '%s'\n",
program_name, XDisplayName (display_name));
}
screen = DefaultScreen(dpy);
root = RootWindow(dpy, screen);
fprintf (stderr, "Time delay = %d\n", time);
for(i=0; i<argc; i++)
{
fprintf (stderr, "Reading %s...", argv[i]);
bitmap[i] = ReadBitmapFile (argv[i], &ww[i], &hh[i], (int *)NULL, (int *)NULL);
fprintf (stderr, "Height=%d, Width=%d\n", hh[i], ww[i]);
}
while(1)
for(i=0; i<argc; i++)
{
int w, h;
w=ww[i];
h=hh[i];
usleep(time);
SetBackgroundToBitmap(bitmap[i], w, h);
}
}
Pixmap ReadBitmapFile(filename, width, height, x_hot, y_hot)
char *filename;
unsigned int *width, *height;
int *x_hot, *y_hot;
{
Pixmap bitmap;
int status;
status = XReadBitmapFile(dpy, root, filename, width,
height, &bitmap, x_hot, y_hot);
if (status == BitmapSuccess)
return(bitmap);
else if (status == BitmapOpenFailed)
fprintf(stderr, "%s: can't open file: %s\n", program_name, filename);
else if (status == BitmapFileInvalid)
fprintf(stderr, "%s: bad bitmap format file: %s\n",
program_name, filename);
else
fprintf(stderr, "%s: insufficient memory for bitmap: %s",
program_name, filename);
exit(1);
/*NOTREACHED*/
}
/*
* SetBackgroundToBitmap: Set the root window background to a caller supplied
* bitmap.
*/
SetBackgroundToBitmap(bitmap, width, height)
Pixmap bitmap;
unsigned int width, height;
{
Pixmap pix;
GC gc;
XGCValues gc_init;
gc_init.foreground = NameToPixel(fore_color, BlackPixel(dpy, screen));
gc_init.background = NameToPixel(back_color, WhitePixel(dpy, screen));
if (reverse) {
unsigned long temp=gc_init.foreground;
gc_init.foreground=gc_init.background;
gc_init.background=temp;
}
gc = XCreateGC(dpy, root, GCForeground|GCBackground, &gc_init);
/*
pix = XCreatePixmap(dpy, root, width, height,
(unsigned int)DefaultDepth(dpy, screen));
XCopyPlane(dpy, bitmap, pix, gc, 0, 0, width, height, 0, 0, (unsigned long)1);
*/
XSetWindowBackgroundPixmap(dpy, root, bitmap);
XFreeGC(dpy, gc);
/*
XFreePixmap(dpy, bitmap);
if (save_colors)
save_pixmap = pix;
else
XFreePixmap(dpy, pix);
*/
XClearWindow(dpy, root);
XFlush(dpy);
unsave_past = 1;
}
unsigned long NameToPixel(name, pixel)
char *name;
unsigned long pixel;
{
XColor ecolor;
if (!name || !*name)
return pixel;
if (!XParseColor(dpy,DefaultColormap(dpy,screen),name,&ecolor)) {
fprintf(stderr,"%s: unknown color \"%s\"\n",program_name,name);
exit(1);
/*NOTREACHED*/
}
if (!XAllocColor(dpy, DefaultColormap(dpy, screen),&ecolor)) {
fprintf(stderr, "%s: unable to allocate color for \"%s\"\n",
program_name, name);
exit(1);
/*NOTREACHED*/
}
if ((ecolor.pixel != BlackPixel(dpy, screen)) &&
(ecolor.pixel != WhitePixel(dpy, screen)) &&
(DefaultVisual(dpy, screen)->class & Dynamic))
save_colors = 1;
return(ecolor.pixel);
}