1 /* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 2001
2 * by Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* The MIT-SHM (Shared Memory) extension is pretty tricky to use.
14 This file contains the common boiler-plate for creating a shared
15 XImage structure, and for making sure that the shared memory segments
16 get allocated and shut down cleanly.
18 This code currently deals only with shared XImages, not with shared Pixmaps.
19 It also doesn't use "completion events", but so far that doesn't seem to
20 be a problem (and I'm not entirely clear on when they would actually be
23 If you don't have man pages for this extension, see
24 http://www.physik.uni-regensburg.de/~scs22156/sofie-0.2/mit-shm.html
25 or in the R6 sources as "xc/doc/specs/Xext/mit-shm.ms", for example,
26 ftp://ftp.x.org/pub/R6.4/xc/doc/specs/Xext/mit-shm.ms
28 (This document seems not to ever remain available on the web in one place
29 for very long; you can search for it by the title, "MIT-SHM -- The MIT
30 Shared Memory Extension".)
32 To monitor the system's shared memory segments, run "ipcs -m".
37 #ifdef HAVE_XSHM_EXTENSION /* whole file */
41 #include <errno.h> /* for perror() */
42 #include <X11/Xutil.h> /* for XDestroyImage() */
45 #include "resources.h" /* for get_string_resource() */
48 # include <X11/Xmu/Error.h>
51 extern char *progname;
54 /* The documentation for the XSHM extension implies that if the server
55 supports XSHM but is not the local machine, the XShm calls will return
56 False; but this turns out not to be the case. Instead, the server
57 throws a BadAccess error. So, we need to catch X errors around all
58 of our XSHM calls, sigh.
61 static Bool shm_got_x_error = False;
62 XErrorHandler old_handler = 0;
64 shm_ehandler (Display *dpy, XErrorEvent *error)
66 shm_got_x_error = True;
69 fprintf (stderr, "\n%s: ignoring X error from XSHM:\n", progname);
70 XmuPrintDefaultErrorMessage (dpy, error, stderr);
71 fprintf (stderr, "\n");
78 #define CATCH_X_ERROR(DPY) do { \
79 XSync((DPY), False); \
80 shm_got_x_error = False; \
81 if (old_handler != shm_ehandler) \
82 old_handler = XSetErrorHandler (shm_ehandler); \
85 #define UNCATCH_X_ERROR(DPY) do { \
86 XSync((DPY), False); \
88 XSetErrorHandler (old_handler); \
94 create_xshm_image (Display *dpy, Visual *visual,
96 int format, char *data,
97 XShmSegmentInfo *shm_info,
98 unsigned int width, unsigned int height)
102 if (!get_boolean_resource("useSHM", "Boolean"))
105 if (!XShmQueryExtension (dpy))
109 image = XShmCreateImage(dpy, visual, depth,
110 format, data, shm_info, width, height);
111 UNCATCH_X_ERROR(dpy);
116 fprintf(stderr, "\n%s: XShmCreateImage(... %d, %d)\n", progname,
120 shm_info->shmid = shmget(IPC_PRIVATE,
121 image->bytes_per_line * image->height,
124 fprintf(stderr, "%s: shmget(IPC_PRIVATE, %d, IPC_CREAT | 0777) ==> %d\n",
125 progname, image->bytes_per_line * image->height, shm_info->shmid);
128 if (shm_info->shmid == -1)
131 sprintf (buf, "%s: shmget failed", progname);
133 XDestroyImage (image);
139 shm_info->readOnly = False;
140 image->data = shm_info->shmaddr = shmat(shm_info->shmid, 0, 0);
143 fprintf(stderr, "%s: shmat(%d, 0, 0) ==> %d\n", progname,
144 shm_info->shmid, (int) image->data);
148 status = XShmAttach(dpy, shm_info);
149 UNCATCH_X_ERROR(dpy);
155 fprintf (stderr, "%s: XShmAttach failed!\n", progname);
156 XDestroyImage (image);
158 shmdt (shm_info->shmaddr);
163 fprintf(stderr, "%s: XShmAttach(dpy, shm_info) ==> True\n", progname);
168 /* Delete the shared segment right now; the segment won't actually
169 go away until both the client and server have deleted it. The
170 server will delete it as soon as the client disconnects, so we
171 should delete our side early in case of abnormal termination.
172 (And note that, in the context of xscreensaver, abnormal
173 termination is the rule rather than the exception, so this would
174 leak like a sieve if we didn't do this...)
176 #### Are we leaking anyway? Perhaps because of the window of
177 opportunity between here and the XShmAttach call above, during
178 which we might be killed? Do we need to establish a signal
179 handler for this case?
181 shmctl (shm_info->shmid, IPC_RMID, 0);
184 fprintf(stderr, "%s: shmctl(%d, IPC_RMID, 0)\n\n", progname,
194 destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info)
199 status = XShmDetach (dpy, shm_info);
200 UNCATCH_X_ERROR(dpy);
204 fprintf (stderr, "%s: XShmDetach failed!\n", progname);
207 fprintf (stderr, "%s: XShmDetach(dpy, shm_info) ==> True\n", progname);
210 XDestroyImage (image);
213 status = shmdt (shm_info->shmaddr);
218 sprintf (buf, "%s: shmdt(0x%lx) failed", progname,
219 (unsigned long) shm_info->shmaddr);
224 fprintf (stderr, "%s: shmdt(shm_info->shmaddr) ==> 0\n", progname);
231 #endif /* HAVE_XSHM_EXTENSION */