kde-base/pykde4: fix bugs in pythonpluginfactorywrapper.c
authorHector Martin <marcan@marcan.st>
Fri, 11 Mar 2016 14:11:34 +0000 (23:11 +0900)
committerMichael Palimaka <kensington@gentoo.org>
Fri, 18 Mar 2016 07:19:23 +0000 (18:19 +1100)
The logic for checking the return value of fork() was inverted,
causing the main process to continue as the child process, while
the parent process execs. This can confuse libraries and
applications that don't expect their PID to suddenly change, and
other misc badness (process gets reparented to init, etc.)

Gentoo-bug: https://bugs.gentoo.org/show_bug.cgi?id=555436

kde-base/pykde4/files/kpythonpluginfactorywrapper.c-r2 [new file with mode: 0644]
kde-base/pykde4/pykde4-4.14.3-r1.ebuild [new file with mode: 0644]

diff --git a/kde-base/pykde4/files/kpythonpluginfactorywrapper.c-r2 b/kde-base/pykde4/files/kpythonpluginfactorywrapper.c-r2
new file mode 100644 (file)
index 0000000..f516f1b
--- /dev/null
@@ -0,0 +1,71 @@
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#define VERSION_LEN 10
+
+#define FORMAT EPREFIX PLUGIN_DIR "/kpython%spluginfactory.so"
+
+static void *handle;
+static void *(*wrapped_qt_plugin_instance)();
+
+static void get_python_version(char* out) {
+       int pipefd[2];
+       pipe(pipefd);
+       pid_t cpid = fork();
+       if (cpid > 0) {
+               close(pipefd[1]);
+               read(pipefd[0], out, VERSION_LEN);
+               close(pipefd[0]);
+               waitpid(cpid, NULL, 0);
+       } else if (cpid < 0) {
+               /* fork failed, guess 2.7 */
+               strcpy(out, "2.7\n");
+               close(pipefd[0]);
+               close(pipefd[1]);
+       } else {
+               close(pipefd[0]);
+               close(1);
+               dup2(pipefd[1], 1);
+               close(pipefd[1]);
+               close(0);
+               char *args[] = { "eselect", "python", "show", "--ABI", "--python2", 0 };
+               execv(EPREFIX "/usr/bin/eselect", args);
+               /* exec failed, guess 2.7 */
+               write(1, "2.7\n", 4);
+               exit(0);
+       }
+}
+
+__attribute__((constructor))
+static void init() {
+       char buf[VERSION_LEN + 1];
+       memset(buf, 0, VERSION_LEN + 1);
+       get_python_version(buf);
+       char *s = buf;
+       while(*s != '\0') {
+               if(*s == '\n') {
+                       *s = '\0';
+                       break;
+               }
+               ++s;
+       }
+       int length = strlen(FORMAT) + strlen(buf) + 1;
+       char *name = malloc(length + 1);
+       snprintf(name, length, FORMAT, buf);
+       handle = dlopen(name, RTLD_NOW);
+       free(name);
+       wrapped_qt_plugin_instance = dlsym(handle, "qt_plugin_instance");
+}
+
+__attribute__((destructor))
+static void fini() {
+       dlclose(handle);
+}
+
+void *qt_plugin_instance() {
+       return wrapped_qt_plugin_instance();
+}
diff --git a/kde-base/pykde4/pykde4-4.14.3-r1.ebuild b/kde-base/pykde4/pykde4-4.14.3-r1.ebuild
new file mode 100644 (file)
index 0000000..64c9fd8
--- /dev/null
@@ -0,0 +1,165 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+EAPI=5
+
+PYTHON_COMPAT=( python{2_7,3_3,3_4} )
+PYTHON_REQ_USE="threads"
+OPENGL_REQUIRED="always"
+CMAKE_MAKEFILE_GENERATOR="emake"
+inherit python-r1 portability kde4-base multilib eutils
+
+DESCRIPTION="Python bindings for KDE4"
+KEYWORDS="~amd64 ~arm ~ppc ~ppc64 ~x86 ~amd64-linux ~x86-linux"
+IUSE="akonadi debug doc examples test"
+HOMEPAGE="https://techbase.kde.org/Development/Languages/Python"
+
+REQUIRED_USE="${PYTHON_REQUIRED_USE}"
+
+RDEPEND="
+       ${PYTHON_DEPS}
+       >=dev-python/PyQt4-4.11.1[${PYTHON_USEDEP},dbus,declarative,script,sql,svg,webkit,X]
+       >=dev-python/sip-4.16.2:=[${PYTHON_USEDEP}]
+       $(add_kdebase_dep kdelibs 'opengl')
+       akonadi? ( $(add_kdeapps_dep kdepimlibs) )
+"
+DEPEND="${RDEPEND}
+       dev-lang/python-exec:2[${PYTHON_USEDEP}]
+       sys-devel/libtool
+"
+
+PATCHES=( "${FILESDIR}/${P}-gcc-5.patch" )
+
+pkg_setup() {
+       kde4-base_pkg_setup
+
+       have_python2=false
+
+       scan_python_versions() {
+               if [[ ${EPYTHON} == python2.* ]]; then
+                       have_python2=true
+               fi
+       }
+       python_foreach_impl scan_python_versions
+
+       if ! ${have_python2}; then
+               ewarn "You do not have a Python 2 version selected."
+               ewarn "kpythonpluginfactory will not be built"
+       fi
+}
+
+src_prepare() {
+       kde4-base_src_prepare
+
+       if ! use examples; then
+               sed -e '/^ADD_SUBDIRECTORY(examples)/s/^/# DISABLED /' -i CMakeLists.txt \
+                       || die "Failed to disable examples"
+       fi
+
+       # See bug 322351
+       use arm && epatch "${FILESDIR}/${PN}-4.14.0-arm-sip.patch"
+
+       sed -e 's/kpythonpluginfactory /kpython${PYTHON_SHORT_VERSION}pluginfactory /g' \
+               -i kpythonpluginfactory/CMakeLists.txt || die
+
+       if ${have_python2}; then
+               mkdir -p "${WORKDIR}/wrapper" || die "failed to copy wrapper"
+               cp "${FILESDIR}/kpythonpluginfactorywrapper.c-r2" "${WORKDIR}/wrapper/kpythonpluginfactorywrapper.c" || die "failed to copy wrapper"
+       fi
+       python_copy_sources
+
+}
+
+src_configure() {
+       configuration() {
+               local mycmakeargs=(
+                       -DWITH_PolkitQt=OFF
+                       -DWITH_QScintilla=OFF
+                       -DPYKDEUIC4_ALTINSTALL=TRUE
+                       -DWITH_Nepomuk=OFF
+                       -DWITH_Soprano=OFF
+                       $(cmake-utils_use_with akonadi KdepimLibs)
+                       -DPYTHON_EXECUTABLE=${PYTHON}
+               )
+               local CMAKE_BUILD_DIR=${S}_build-${PYTHON_ABI}
+               kde4-base_src_configure
+       }
+
+       python_foreach_impl run_in_build_dir configuration
+}
+
+echo_and_run() {
+       echo "$@"
+       "$@"
+}
+
+src_compile() {
+       compilation() {
+               local CMAKE_BUILD_DIR=${S}_build-${PYTHON_ABI}
+               kde4-base_src_compile
+       }
+       python_foreach_impl run_in_build_dir compilation
+
+       if ${have_python2}; then
+               pushd "${WORKDIR}/wrapper" > /dev/null
+               echo_and_run libtool --tag=CC --mode=compile $(tc-getCC) \
+                       -shared \
+                       ${CFLAGS} ${CPPFLAGS} \
+                       -DEPREFIX="\"${EPREFIX}\"" \
+                       -DPLUGIN_DIR="\"/usr/$(get_libdir)/kde4\"" -c \
+                       -o kpythonpluginfactorywrapper.lo \
+                       kpythonpluginfactorywrapper.c
+               echo_and_run libtool --tag=CC --mode=link $(tc-getCC) \
+                       -shared -module -avoid-version \
+                       ${CFLAGS} ${LDFLAGS} \
+                       -o kpythonpluginfactory.la \
+                       -rpath "${EPREFIX}/usr/$(get_libdir)/kde4" \
+                       kpythonpluginfactorywrapper.lo \
+                       $(dlopen_lib)
+               popd > /dev/null
+       fi
+}
+
+src_test() {
+       python_foreach_impl run_in_build_dir kde4-base_src_test
+}
+
+src_install() {
+       installation() {
+               emake DESTDIR="${D}" install
+
+               mkdir -p "${D%/}$(python_get_scriptdir)" || die
+               mv "${ED%/}/usr/bin/pykdeuic4-${EPYTHON/python/}" \
+                       "${D%/}$(python_get_scriptdir)"/pykdeuic4 || die
+
+               python_fix_shebang "${D%/}$(python_get_scriptdir)"/pykdeuic4
+               python_optimize
+       }
+       python_foreach_impl run_in_build_dir installation
+
+       dosym ../lib/python-exec/python-exec2 /usr/bin/pykdeuic4
+
+       # As we don't call the eclass's src_install, we have to install the docs manually
+       DOCS=("${S}"/{AUTHORS,NEWS,README})
+       use doc && HTML_DOCS=("${S}/docs/html/")
+       einstalldocs
+
+       if ${have_python2}; then
+               pushd "${WORKDIR}/wrapper" > /dev/null
+               echo_and_run libtool --mode=install install kpythonpluginfactory.la "${ED}/usr/$(get_libdir)/kde4/kpythonpluginfactory.la"
+               rm "${ED}/usr/$(get_libdir)/kde4/kpythonpluginfactory.la"
+               popd > /dev/null
+       fi
+}
+
+pkg_postinst() {
+       kde4-base_pkg_postinst
+
+       if use examples; then
+               echo
+               elog "PyKDE4 examples have been installed to"
+               elog "${EPREFIX}/usr/share/apps/${PN}/examples"
+               echo
+       fi
+}