--- origsrc/qtbase-opensource-src-5.3.2/src/plugins/platforms/xcb/qxcbbackingstore.cpp 2014-09-11 11:48:06.000000000 +0100 +++ src/qtbase-opensource-src-5.3.2/src/plugins/platforms/xcb/qxcbbackingstore.cpp 2015-02-13 17:30:11.410525500 +0000 @@ -75,6 +75,7 @@ public: private: void destroy(); + static bool isShmSupported(); xcb_shm_segment_info_t m_shm_info; @@ -88,6 +89,44 @@ private: QRegion m_dirty; }; +static bool shmNotSupported = false; + +static void +SigSysHandler(int signo) +{ + shmNotSupported = true; +} + +bool +QXcbShmImage::isShmSupported() +{ + static bool checked = false; + if (!checked) + { + void (*oldHandler)(int); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + shmNotSupported = false; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, NULL); + } + else + { + /* Allocation failed */ + shmNotSupported = true; + } + signal(SIGSYS, oldHandler); + checked = true; + } + return (!shmNotSupported); +} + QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format) : QXcbObject(screen->connection()) , m_gc(0) @@ -116,7 +155,9 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *s if (!segmentSize) return; - int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); + int id = -1; + if (isShmSupported()) + id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); if (id == -1) qWarning("QXcbShmImage: shmget() failed (%d) for size %d (%dx%d)", errno, segmentSize, size.width(), size.height()); @@ -130,7 +171,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *s xcb_generic_error_t *error = NULL; if (shm_present) error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); - if (!shm_present || error) { + if (!shm_present || error || (id == -1)) { free(error); shmdt(m_shm_info.shmaddr);