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); }