[Xquartz-changes] xserver: Branch 'server-1.11-apple' - 5 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Thu May 12 15:46:01 PDT 2011


Rebased ref, commits from common ancestor:
commit 524a1aa043597605d6771cc54b1de0a42be0ab31
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu May 12 15:45:29 2011 -0700

    XQuartz: Add a LOGGING section to our man page
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/man/Xquartz.man b/hw/xquartz/man/Xquartz.man
index ad5ce28..19e8efb 100644
--- a/hw/xquartz/man/Xquartz.man
+++ b/hw/xquartz/man/Xquartz.man
@@ -102,9 +102,32 @@ Same as fake_button3 above.
 .TP 8
 .B "\-depth \fIdepth\fP"
 Same as depth above.
+.SH LOGGING
+XQuartz stores a server log at ~/Library/Logs/X11.__bundle_id_prefix__.log which
+is analogous to /var/log/Xorg.#.log on systems that use the XFree86 DDX such as
+Linux, BSD, and Solaris.
+.PP
+In addition to this server log, XQuartz sends messages to syslogd(8) using
+asl(3).  These logs are sent to the __bundle_id_prefix__ facility, and you can
+watch these logs using the following syslog(1) command:
+.TP 8
+.B $ syslog -w -k Facility __bundle_id_prefix__
+.PP
+By default, XQaurtz sets an ASL mask which prevents it from logging messages
+below the ASL_LEVEL_WARNING level (meaning almost all logging is done strictly
+to the file referenced above).  To force XQuartz to send all log messages to
+syslogd(8), you can adjust this mask using the following syslog(1) command:
+.TP 8
+.B $ syslog -c X11.bin -d
+.PP
+The stdout and stderr messages printed by any process launched by XQuartz will
+be redirected to this syslog facility with a priority level of ASL_LEVEL_INFO
+and ASL_LEVEL_NOTICE respectively.  In order to see these messages in syslog,
+you will need to adjust XQuartz's asl mask as above but using -i or -n
+instead of -d.
 .SH "SEE ALSO"
 .PP
-X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1)
+X(__miscmansuffix__), Xserver(1), xdm(1), xinit(1), syslog(1), syslogd(8)
 .PP
 http://xquartz.macosforge.org
 .PP
commit d8171036ea5c7f5c8d218462ec47ccf74c3af6ab
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Thu May 12 15:15:40 2011 -0700

    Fix a typo: laucnd instead of launchd
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/man/Xquartz.man b/hw/xquartz/man/Xquartz.man
index 4471947..ad5ce28 100644
--- a/hw/xquartz/man/Xquartz.man
+++ b/hw/xquartz/man/Xquartz.man
@@ -16,72 +16,72 @@ OS X handles the desktop background.
 .SH CUSTOMIZATION
 \fIXquartz\fP can be customized using the defaults(1) command. The available options are:
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 enable_fake_buttons -boolean true
+.B defaults write __bundle_id_prefix__.X11 enable_fake_buttons -boolean true
 Emulates a 3 button mouse using modifier keys. By default, the Command modifier
 is used to emulate button 2 and Option is used for button 3. Thus, clicking the
 first mouse button while holding down Command will act like clicking
 button 2. Holding down Option will simulate button 3.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 fake_button2 \fImodifiers\fP
+.B defaults write __bundle_id_prefix__.X11 fake_button2 \fImodifiers\fP
 Change the modifier keys used to emulate the second mouse button. By default,
 Command is used to emulate the second button. Any combination of the following
 modifier names may be used: {l,r,}shift, {l,r,}option, {l,r,}control, {l,r,}command, fn
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 fake_button3 \fImodifiers\fP
+.B defaults write __bundle_id_prefix__.X11 fake_button3 \fImodifiers\fP
 Change the modifier keys used to emulate the second mouse button. By default,
 Command is used to emulate the second button. Any combination of the following
 modifier names may be used: {l,r,}shift, {l,r,}option, {l,r,}control, {l,r,}command, fn
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 fullscreen_hotkeys -boolean true
+.B defaults write __bundle_id_prefix__.X11 fullscreen_hotkeys -boolean true
 Enable OSX hotkeys while in fullscreen
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 fullscreen_menu -boolean true
+.B defaults write __bundle_id_prefix__.X11 fullscreen_menu -boolean true
 Show the OSX menu while in fullscreen
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 no_quit_alert -boolean true
+.B defaults write __bundle_id_prefix__.X11 no_quit_alert -boolean true
 Disables the alert dialog displayed when attempting to quit X11.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 no_auth -boolean true
+.B defaults write __bundle_id_prefix__.X11 no_auth -boolean true
 Stops the X server requiring that clients authenticate themselves when
 connecting.  See Xsecurity(__miscmansuffix__).
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 nolisten_tcp -boolean false
+.B defaults write __bundle_id_prefix__.X11 nolisten_tcp -boolean false
 This will tell the server to listen and accept TCP connections.  Doing this without enabling
 xauth is a possible security concern.  See Xsecurity(__miscmansuffix__).
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 enable_system_beep -boolean false
+.B defaults write __bundle_id_prefix__.X11 enable_system_beep -boolean false
 Don't use the standard system beep effect for X11 alerts.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 enable_key_equivalents -boolean false
+.B defaults write __bundle_id_prefix__.X11 enable_key_equivalents -boolean false
 Disable menu keyboard equivalents while X11 windows are focused.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 depth \fIdepth\fP
+.B defaults write __bundle_id_prefix__.X11 depth \fIdepth\fP
 Specifies the color bit depth to use. Currently only 15, and 24 color
 bits per pixel are supported. If not specified, or a value of -1 is specified,
 defaults to the depth of the main display.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_keymap -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_keymap -boolean true
 Keep the X11 keymap up to date with the OSX system keymap.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 option_sends_alt -boolean true
+.B defaults write __bundle_id_prefix__.X11 option_sends_alt -boolean true
 The Option key will send Alt_L and Alt_R instead of Mode_switch.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_pasteboard -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_pasteboard -boolean true
 Enable syncing between the OSX pasteboard and clipboard/primary selection buffers in X11.  This option needs to be true for any of the other pasteboard sync options to have an effect.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_pasteboard_to_clipboard -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_pasteboard_to_clipboard -boolean true
 Update the X11 CLIPBOARD when the OSX NSPasteboard is updated.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_pasteboard_to_primary -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_pasteboard_to_primary -boolean true
 Update the the X11 PRIMARY buffer when the OSX NSPasteboard is updated.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_clipboard_to_pasteboard -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_clipboard_to_pasteboard -boolean true
 Update the the OSX NSPasteboard when the X11 CLIPBOARD is updated.  Note that enabling this option causes the clipboard synchronization to act as a clipboard manager in X11.  This makes it impossible to use xclipboard, klipper, or any other such clipboard managers.  If you want to use any of these programs, you must disable this option.
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 sync_primary_on_select -boolean true
+.B defaults write __bundle_id_prefix__.X11 sync_primary_on_select -boolean true
 This option defaults to false and is provided only "for experts."  It updates the NSPasteboard whenever a new X11 selection is made (rather than requiring you to hit cmd-c to copy the selection to the NSPasteboard).  Since the X11 protocol does not require applications to send notification when they change selection, this might not work in all cases (if you run into this problem, try selecting text in another application first, then selecting the text you want).
 .TP 8
-.B defaults write __laucnd_id_prefix__.X11 enable_test_extensions -boolean true
+.B defaults write __bundle_id_prefix__.X11 enable_test_extensions -boolean true
 This option defaults to false and is only accessible through the command line.  Enable this option to turn on the DEC-XTRAP, RECORD, and XTEST extensions in the server.
 .SH OPTIONS
 .PP
diff --git a/manpages.am b/manpages.am
index 03089e3..ea969cc 100644
--- a/manpages.am
+++ b/manpages.am
@@ -24,7 +24,7 @@ MAN_SUBSTS += 	-e 's|__logdir__|$(logdir)|g' \
 		-e 's|__sysconfdir__|$(sysconfdir)|g' \
 		-e 's|__xconfigdir__|$(__XCONFIGDIR__)|g' \
 		-e 's|__xkbdir__|$(XKB_BASE_DIRECTORY)|g' \
-		-e 's|__laucnd_id_prefix__|$(BUNDLE_ID_PREFIX)|g' \
+		-e 's|__bundle_id_prefix__|$(BUNDLE_ID_PREFIX)|g' \
 		-e 's|__modulepath__|$(DEFAULT_MODULE_PATH)|g' \
 		-e 's|__default_font_path__|$(COMPILEDDEFAULTFONTPATH)|g' \
 		-e '\|$(COMPILEDDEFAULTFONTPATH)| s|/,|/, |g'
commit 143b35eca547309bc03330f51aed19d98d69ac61
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Wed May 11 15:23:17 2011 -0700

    XQuartz: Add API which will allow redirection of stdout/stderr to ASL
    
    In order to improve logging in XQuartz, stdout and stderr should be redirected
    to ASL (syslog).  This code provides an API for doing that.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/hw/xquartz/Makefile.am b/hw/xquartz/Makefile.am
index 76f624d..a7cc012 100644
--- a/hw/xquartz/Makefile.am
+++ b/hw/xquartz/Makefile.am
@@ -33,7 +33,8 @@ libXquartz_la_SOURCES = \
 	quartzCocoa.m \
 	quartzKeyboard.c \
 	quartzStartup.c \
-	quartzRandR.c
+	quartzRandR.c \
+	console_redirect.c
 
 EXTRA_DIST = \
 	X11Application.h \
@@ -49,4 +50,5 @@ EXTRA_DIST = \
 	quartzKeyboard.h \
 	quartzRandR.h \
 	sanitizedCarbon.h \
-	sanitizedCocoa.h
+	sanitizedCocoa.h \
+	console_redirect.h
diff --git a/hw/xquartz/console_redirect.c b/hw/xquartz/console_redirect.c
new file mode 100644
index 0000000..87d69d5
--- /dev/null
+++ b/hw/xquartz/console_redirect.c
@@ -0,0 +1,418 @@
+/* Copyright (c) 2011 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#else
+#define DEBUG_CONSOLE_REDIRECT 1
+#define HAVE_DISPATCH 1
+#endif
+
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <asl.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "console_redirect.h"
+
+#define BUF_SIZE 512
+
+#ifdef HAVE_DISPATCH
+#include <dispatch/dispatch.h>
+
+static dispatch_queue_t redirect_serial_q;
+static dispatch_group_t read_source_group;
+#else
+#include <pthread.h>
+
+static pthread_t redirect_pthread;
+static pthread_mutex_t redirect_fds_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int kq;
+
+/* Notifications to our reader thread */
+#define ASL_REDIRECT_TERMINATE ((void *)(uintptr_t)1)
+#endif
+
+typedef struct {
+    int level;
+    aslclient asl;
+    aslmsg msg;
+
+    /* Buffered reading */
+    char *buf;
+    char *w;
+
+#ifdef HAVE_DISPATCH
+    dispatch_source_t read_source;
+#endif
+} asl_redirect;
+
+static asl_redirect *redirect_fds = NULL;
+static int n_redirect_fds = 0;
+
+/* Read from the FD until there is no more to read and redirect to ASL.
+ * Preconditions:
+ *      1: pthread_mutex_lock lock is held (pthreads) or called
+ *         from the appropriate serial queue for operating on
+ *         redirect_fds
+ *      2: fd corresponds to a valid entry in redirect_fds
+ *
+ * Return values:
+ *      If the pipe is closed, EOF is returned regardless of how many bytes
+ *      were processed.  If the pipe is still open, the number of read bytes
+ *      is returned.
+ */
+static inline int _read_redirect(int fd, int flush) {
+    int total_read = 0;
+    int nbytes;
+    asl_redirect *aslr = &redirect_fds[fd];
+
+    while((nbytes = read(fd, aslr->w, BUF_SIZE - (aslr->w - aslr->buf) - 1)) > 0) {
+        char *s, *p;
+
+        /* Increment our returned number read */
+        total_read += nbytes;
+
+        nbytes += (aslr->w - aslr->buf);
+        aslr->buf[nbytes] = '\0';
+
+        /* One line at a time */
+        for(p=aslr->buf; *p && (p - aslr->buf) < nbytes; p = s + 1) {
+            // Find null or \n
+            for(s=p; *s && *s != '\n'; s++);
+            if(*s == '\n') {
+                *s='\0';
+                asl_log(aslr->asl, aslr->msg, aslr->level, "%s", p);
+            } else if(aslr->buf != p) {
+                memmove(aslr->buf, p, BUF_SIZE);
+                aslr->w = aslr->buf + (s - p);
+                break;
+            } else if(nbytes == BUF_SIZE - 1) {
+                asl_log(aslr->asl, aslr->msg, aslr->level, "%s", p);
+                aslr->w = aslr->buf;
+                break;
+            }
+        }
+    }
+
+    /* Flush if requested or we're at EOF */
+    if(flush || nbytes == 0) {
+        if(aslr->w > aslr->buf) {
+            *aslr->w = '\0';
+            asl_log(aslr->asl, aslr->msg, aslr->level, "%s", aslr->buf);
+        }
+    }
+
+    if(nbytes == 0)
+        return EOF;
+    return total_read;
+}
+
+#ifdef HAVE_DISPATCH
+static void read_from_source(void *_source) {
+    dispatch_source_t source = (dispatch_source_t)_source;
+    int fd = dispatch_source_get_handle(source);
+    if(_read_redirect(fd, 0) == EOF) {
+        dispatch_source_cancel(source);
+    }
+}
+
+static void cancel_source(void *_source) {
+    dispatch_source_t source = (dispatch_source_t)_source;
+    int fd = dispatch_source_get_handle(source);
+    asl_redirect *aslr = &redirect_fds[fd];
+
+    /* Flush the buffer */
+    _read_redirect(fd, 1);
+
+    close(fd);
+    free(aslr->buf);
+    memset(aslr, 0, sizeof(*aslr));
+    dispatch_release(source);
+    dispatch_group_leave(read_source_group);
+}
+
+#else /* !HAVE_DISPATCH */
+static void *redirect_thread(void *ctx __unused) {
+    struct kevent ev;
+    int n;
+
+    while(1) {
+        n = kevent(kq, NULL, 0, &ev, 1, NULL);
+
+        /* Bail on errors */
+        if(n < 0) {
+            asl_log(NULL, NULL, ASL_LEVEL_ERR, "kevent failure: %s", strerror(errno));
+            break;
+        }
+        
+        /* This should not happen */
+        if(n == 0)
+            continue;
+
+        switch(ev.filter) {
+            case EVFILT_READ:
+                pthread_mutex_lock(&redirect_fds_lock);
+                {
+                    int fd = ev.ident;
+                    int close_fd = 0;
+                    asl_redirect *aslr = &redirect_fds[fd];
+
+                    if(fd < 0 || fd >= n_redirect_fds || aslr->buf == NULL) {
+                        asl_log(NULL, NULL, ASL_LEVEL_ERR, "Unexpected file descriptor: %d", fd);
+                        goto next;
+                    }
+
+                    if(ev.flags & EV_EOF) {
+                        close_fd = 1;
+                        if(EOF != _read_redirect(fd, 1)) {
+                            asl_log(NULL, NULL, ASL_LEVEL_ERR, "kevent reported EOF on %d, but read doesn't concur.", fd);
+                        }
+                    } else {
+                        close_fd = (EOF == _read_redirect(fd, 0));
+                    }
+                    
+                    if(close_fd) {
+                        EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
+                        kevent(kq, &ev, 1, NULL, 0, NULL);
+                        close(fd);
+                        free(aslr->buf);
+                        memset(aslr, 0, sizeof(*aslr));
+                    }
+                }
+                next:
+                pthread_mutex_unlock(&redirect_fds_lock);
+
+            case EVFILT_TIMER:
+                if(ev.udata == ASL_REDIRECT_TERMINATE)
+                    return NULL;
+
+            default:
+                ;;
+        }
+    }
+
+    return NULL;
+}
+#endif
+
+static void redirect_atexit(void) {
+    /* stdout is linebuffered, so flush the buffer */
+    if(redirect_fds[STDOUT_FILENO].buf)
+        fflush(stdout);
+
+#ifdef HAVE_DISPATCH
+    {
+        int i;
+
+        /* Cancel all of our dispatch sources, so they flush to ASL */
+        for(i=0; i < n_redirect_fds; i++)
+            if(redirect_fds[i].read_source)
+                dispatch_source_cancel(redirect_fds[i].read_source);
+
+        /* Wait at least three seconds for our sources to flush to ASL */
+        dispatch_group_wait(read_source_group, dispatch_time(DISPATCH_TIME_NOW, 3LL * NSEC_PER_SEC));
+    }
+#else
+    {
+        struct kevent ev;
+
+        /* Tell our reader thread it is time to pack up and go home */
+        EV_SET(&ev, 0, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 0, ASL_REDIRECT_TERMINATE);
+        kevent(kq, &ev, 1, NULL, 0, NULL);
+    
+        pthread_join(redirect_pthread, NULL);
+    }
+#endif
+}
+
+#ifdef HAVE_DISPATCH
+static void xq_asl_init(void *ctx __unused)
+#else
+static void xq_asl_init(void)
+#endif
+{
+    assert((redirect_fds = calloc(16, sizeof(*redirect_fds))) != NULL);
+    n_redirect_fds = 16;
+
+#ifdef HAVE_DISPATCH
+    redirect_serial_q = dispatch_queue_create("com.apple.asl-redirect", NULL);
+    assert(redirect_serial_q != NULL);
+
+    read_source_group = dispatch_group_create();
+    assert(read_source_group != NULL);
+#else
+    assert((kq = kqueue()) != -1);
+    assert(pthread_create(&redirect_pthread, NULL, redirect_thread, NULL) == 0);
+#endif
+
+    atexit(redirect_atexit);
+}
+
+int xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd) {
+#ifdef HAVE_DISPATCH
+    int err __block = 0;
+    static dispatch_once_t once_control;
+    dispatch_once_f(&once_control, NULL, xq_asl_init);
+#else
+    int err = 0;
+    static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+    assert(pthread_once(&once_control, xq_asl_init) == 0);
+#endif
+    
+    if(fd < 0)
+        return EBADF;
+    
+#ifdef HAVE_DISPATCH
+#define BLOCK_DONE return
+    dispatch_sync(redirect_serial_q, ^
+#else
+#define BLOCK_DONE goto done
+    assert(pthread_mutex_lock(&redirect_fds_lock) == 0);
+#endif
+    {
+        /* Reallocate if we need more space */
+        if(fd >= n_redirect_fds) {
+            size_t new_n = 1 << (ffs(fd) + 1);
+            asl_redirect *new_array = realloc(redirect_fds, new_n * sizeof(*redirect_fds));
+            if(!new_array) {
+                err = errno;
+                BLOCK_DONE;
+            }
+            redirect_fds = new_array;
+            memset(redirect_fds + n_redirect_fds, 0, new_n - n_redirect_fds);
+            n_redirect_fds = new_n;
+        }
+        
+        /* If we're already listening on it, return error. */
+        if(redirect_fds[fd].buf != NULL) {
+            err = EBADF;
+            BLOCK_DONE;
+        }
+        
+        /* Initialize our buffer */
+        redirect_fds[fd].buf = (char *)malloc(BUF_SIZE);
+        if(redirect_fds[fd].buf == NULL) {
+            err = errno;
+            BLOCK_DONE;
+        }
+        redirect_fds[fd].w = redirect_fds[fd].buf;
+        
+        /* Store our ASL settings */
+        redirect_fds[fd].level = level;
+        redirect_fds[fd].asl = asl;
+        redirect_fds[fd].msg = msg;
+        
+        /* Don't block on reads from this fd */
+        fcntl(fd, F_SETFL, O_NONBLOCK);
+        
+        /* Start listening */
+#ifdef HAVE_DISPATCH
+        {
+            dispatch_source_t read_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, redirect_serial_q);
+            redirect_fds[fd].read_source = read_source;
+            dispatch_set_context(read_source, read_source);
+            dispatch_source_set_event_handler_f(read_source, read_from_source);
+            dispatch_source_set_cancel_handler_f(read_source, cancel_source);
+            dispatch_group_enter(read_source_group);
+            dispatch_resume(read_source);
+        }
+#else
+        {
+            struct kevent ev;
+            EV_SET(&ev, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
+            kevent(kq, &ev, 1, NULL, 0, NULL);
+        }
+#endif
+    }
+#ifdef HAVE_DISPATCH
+    );
+#else
+done:
+    assert(pthread_mutex_unlock(&redirect_fds_lock) == 0);
+#endif
+#undef BLOCK_DONE
+    
+    return err;
+}
+
+int xq_asl_capture_fd(aslclient asl, aslmsg msg, int level, int fd) {
+    int pipepair[2];
+    
+    /* Create pipe */
+    if(pipe(pipepair) == -1)
+        return errno;
+    
+    /* Close the read fd but not the write fd on exec */
+    if(fcntl(pipepair[0], F_SETFD, FD_CLOEXEC) == -1)
+        return errno;
+
+    /* Replace the existing fd */
+    if(dup2(pipepair[1], fd) == -1) {
+        close(pipepair[0]);
+        close(pipepair[1]);
+        return errno;
+    }
+
+    /* If we capture STDOUT_FILENO, make sure we linebuffer stdout */
+    if(fd == STDOUT_FILENO)
+        setlinebuf(stdout);
+    
+    /* Close the duplicate fds since they've been reassigned */
+    close(pipepair[1]);
+
+    /* Hand off the read end of our pipe to xq_asl_log_fd */
+    return xq_asl_log_fd(asl, msg, level, pipepair[0]);
+}
+
+#ifdef DEBUG_CONSOLE_REDIRECT
+int main(int argc __unused, char **argv __unused) {
+    xq_asl_capture_fd(NULL, NULL, ASL_LEVEL_NOTICE, STDOUT_FILENO);
+    xq_asl_capture_fd(NULL, NULL, ASL_LEVEL_ERR, STDERR_FILENO);
+
+    fprintf(stderr, "TEST ERR1\n");
+    fprintf(stdout, "TEST OUT1\n");
+    fprintf(stderr, "TEST ERR2\n");
+    fprintf(stdout, "TEST OUT2\n");
+    system("/bin/echo SYST OUT");
+    system("/bin/echo SYST ERR >&2");
+    fprintf(stdout, "TEST OUT3\n");
+    fprintf(stdout, "TEST OUT4\n");
+    fprintf(stderr, "TEST ERR3\n");
+    fprintf(stderr, "TEST ERR4\n");
+
+    exit(0);
+}
+#endif
diff --git a/hw/xquartz/console_redirect.h b/hw/xquartz/console_redirect.h
new file mode 100644
index 0000000..94520a3
--- /dev/null
+++ b/hw/xquartz/console_redirect.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2011 Apple Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
+ * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name(s) of the above
+ * copyright holders shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without
+ * prior written authorization.
+ */
+
+#ifndef _XQUARTZ_CONSOLE_REDIRECT_H_
+#define _XQUARTZ_CONSOLE_REDIRECT_H_
+
+#include <asl.h>
+
+/* The given fd is replaced with a pipe.  Anything written to it will will be
+ * logged to ASL.
+ */
+int xq_asl_capture_fd(aslclient asl, aslmsg msg, int level, int fd);
+
+/* The given fd is read from and passed along to ASL until all write ends of the
+ * pipe are closed. Once the last writer has closed the pipe, we close our end.
+ */
+int xq_asl_log_fd(aslclient asl, aslmsg msg, int level, int fd);
+
+#endif
commit 10e0cb48e91987a97894638597d64c62b34db27e
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Apr 30 13:08:25 2010 -0700

    Workaround the GC clipping problem in miPaintWindow and add some debugging output.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/mi/miexpose.c b/mi/miexpose.c
index 94258b8..4f25c23 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -521,6 +521,7 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
+#include "../fb/fb.h"
 #endif 
 
 void
@@ -548,24 +549,37 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     Bool	solid = TRUE;
     DrawablePtr	drawable = &pWin->drawable;
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
+    ErrorF("      Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
+	                               prgn->extents.x2 - prgn->extents.x1,
+	                               prgn->extents.y2 - prgn->extents.y1);
+    ErrorF("      Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
+	                                       pWin->winSize.extents.x1, pWin->winSize.extents.y1,
+	                                       pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
+					       pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
+    ErrorF("     Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
+				       pWin->drawable.width, pWin->drawable.height);
+#endif
+
 #ifdef ROOTLESS
     if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
 	return;
-
-    if(IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-    
-        if(pWin->backgroundState == ParentRelative) {
-            if((what == PW_BACKGROUND) || 
-               (what == PW_BORDER && !pWin->borderIsPixel))
-                RootlessSetPixmapOfAncestors(pWin);
-        }
-    }
 #endif
     
     if (what == PW_BACKGROUND)
     {
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+
+	    if(pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	while (pWin->backgroundState == ParentRelative)
 	    pWin = pWin->parent;
 
@@ -587,6 +601,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     {
 	PixmapPtr   pixmap;
 
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+	    
+	    if(!pWin->borderIsPixel &&
+		pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	tile_x_off = drawable->x;
 	tile_y_off = drawable->y;
 	
@@ -595,6 +621,12 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
 	    return;
 	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
 	drawable = &pixmap->drawable;
+
+#ifdef XQUARTZ_CLIP_DEBUG
+	ErrorF("     Draw: %d %d %d %d\n",
+	       drawable->x, drawable->y, drawable->width, drawable->height);    
+#endif
+	
 #ifdef COMPOSITE
 	draw_x_off = pixmap->screen_x;
 	draw_y_off = pixmap->screen_y;
@@ -657,6 +689,57 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     ChangeGC (NullClient, pGC, gcmask, gcval);
     ValidateGC (drawable, pGC);
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
+#endif
+    
+#ifdef XQUARTZ
+    /* Looks like our clipping isn't set right for some reason:
+     * http://xquartz.macosforge.org/trac/ticket/290
+     */
+    if(what == PW_BORDER) {
+
+#if 0
+	if(solid) {
+#if 1
+	    fbFillRegionSolid(&pWin->drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       pWin->drawable.bitsPerPixel));
+#else
+	    fbFillRegionSolid(drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       drawable->bitsPerPixel));
+#endif
+	    return;
+	}
+#endif
+    
+	pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
+	pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
+	
+	if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
+	    pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
+	if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
+	    pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
+    }
+#endif
+
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);    
+#endif
+
     numRects = RegionNumRects(prgn);
     pbox = RegionRects(prgn);
     for (i= numRects; --i >= 0; pbox++, prect++)
commit da937297f1b07001951f6eb893def66b433bf984
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Sat Oct 30 14:55:06 2010 -0700

    configure.ac: Add -fno-strict-aliasing to CFLAGS
    
    This should address https://bugs.freedesktop.org/show_bug.cgi?id=31238
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/configure.ac b/configure.ac
index a474073..a54362d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,6 +86,12 @@ XORG_PROG_RAWCPP
 # easier overrides at build time.
 XSERVER_CFLAGS='$(CWARNFLAGS)'
 
+dnl Explicitly add -fno-strict-aliasing since this option should disappear
+dnl from util-macros CWARNFLAGS
+if  test "x$GCC" = xyes ; then
+    XSERVER_CFLAGS="$XSERVER_CFLAGS -fno-strict-aliasing"
+fi
+
 dnl Check for dtrace program (needed to build Xserver dtrace probes)
 dnl Also checks for <sys/sdt.h>, since some Linux distros have an 
 dnl ISDN trace program named dtrace


More information about the Xquartz-changes mailing list