Skip to content

Commit

Permalink
kde-base/pykde4: fix bugs in pythonpluginfactorywrapper.c
Browse files Browse the repository at this point in the history
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
  • Loading branch information
marcan authored and kensington committed Mar 18, 2016
1 parent e3d8a51 commit 22aa5c8
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 0 deletions.
71 changes: 71 additions & 0 deletions kde-base/pykde4/files/kpythonpluginfactorywrapper.c-r2
@@ -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();
}
165 changes: 165 additions & 0 deletions kde-base/pykde4/pykde4-4.14.3-r1.ebuild
@@ -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
}

0 comments on commit 22aa5c8

Please sign in to comment.