summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Coopersmith <alan.coopersmith@sun.com>2009-03-26 23:04:24 -0700
committerAlan Coopersmith <alan.coopersmith@sun.com>2009-04-09 17:10:12 -0700
commit98f4179156391752e6688339487458ad7828abf4 (patch)
tree862ea6c90cc6a72ba30ce2ace5d54f0baf6c4df3
parenta0b6a363dca8ce0dc6f4eb79333e48496153cd67 (diff)
Use RTLD_DI_SETSIGNAL to catch runtime dynamic loader errors and clean up
Based on fix for Sun bug 6813925: Xorg needs to catch ld.so.1 failure so it can close down devices cleanly <http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6813925> Signed-off-by: Alan Coopersmith <alan.coopersmith@sun.com>
-rw-r--r--configure.ac2
-rw-r--r--os/osinit.c20
2 files changed, 21 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index f4e1dbb04..93ef0bd23 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,7 +105,7 @@ AM_CONDITIONAL(XSERVER_DTRACE, [test "x$WDTRACE" != "xno"])
AC_HEADER_DIRENT
AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h])
+AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h])
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
diff --git a/os/osinit.c b/os/osinit.c
index 34d8378a6..b7bd0763b 100644
--- a/os/osinit.c
+++ b/os/osinit.c
@@ -56,6 +56,9 @@ SOFTWARE.
#include <X11/Xos.h>
#include <signal.h>
#include <errno.h>
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
#include "dixstruct.h"
@@ -113,6 +116,14 @@ OsSigHandler(int signo, siginfo_t *sip, void *unused)
OsSigHandler(int signo)
#endif
{
+#ifdef RTLD_DI_SETSIGNAL
+ const char *dlerr = dlerror();
+
+ if (dlerr) {
+ LogMessage(X_ERROR, "Dynamic loader error: %s\n", dlerr);
+ }
+#endif /* RTLD_DI_SETSIGNAL */
+
if (OsSigWrapper != NULL) {
if (OsSigWrapper(signo) == 0) {
/* ddx handled signal and wants us to continue */
@@ -180,6 +191,15 @@ OsInit(void)
}
}
+#ifdef RTLD_DI_SETSIGNAL
+ /* Tell runtime linker to send a signal we can catch instead of SIGKILL
+ * for failures to load libraries/modules at runtime so we can clean up
+ * after ourselves.
+ */
+ int failure_signal = SIGQUIT;
+ dlinfo(RTLD_SELF, RTLD_DI_SETSIGNAL, &failure_signal);
+#endif
+
#if !defined(__SCO__) && !defined(__CYGWIN__) && !defined(__UNIXWARE__)
fclose(stdin);
fclose(stdout);