美文网首页视频编码学习之路
Android NDK缺失pthread_cancel和pthr

Android NDK缺失pthread_cancel和pthr

作者: 团不慌 | 来源:发表于2019-04-09 16:42 被阅读1次

Android NDKv5版本后不再提供全部的POSIX线程库的API(比如pthread_cancelpthread_setcancelstate)。原因之一是线程被标记结束后不一定会把自己拥有的资源释放掉,甚至不一定会结束,因此很可能造成内存泄露或死锁等问题,而这些问题在移动设备上更加突出[1]

比较安全的方法是使用更安全pthread_kill函数代替,有关pthread_kill的功能讲解和替换方式可以参见这篇博客


此处仅记录ffmpeg编译android版本时对应的问题及解决。使用ndk-r14b编译arm64时报错:

libavformat/udp.c: In function 'circular_buffer_task_rx':
libavformat/udp.c:499:5: error: implicit declaration of function 'pthread_setcancelstate' [-Werror=implicit-function-declaration]
     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
     ^
libavformat/udp.c:499:28: error: 'PTHREAD_CANCEL_DISABLE' undeclared (first use in this function)
     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
                            ^
libavformat/udp.c:499:28: note: each undeclared identifier is reported only once for each function it appears in
libavformat/udp.c:513:32: error: 'PTHREAD_CANCEL_ENABLE' undeclared (first use in this function)
         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate);
                                ^
libavformat/udp.c: In function 'circular_buffer_task_tx':
libavformat/udp.c:561:28: error: 'PTHREAD_CANCEL_DISABLE' undeclared (first use in this function)
     pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancelstate);
                            ^
libavformat/udp.c:596:32: error: 'PTHREAD_CANCEL_ENABLE' undeclared (first use in this function)
         pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancelstate);
                                ^
libavformat/udp.c: In function 'udp_close':
libavformat/udp.c:1142:13: error: implicit declaration of function 'pthread_cancel' [-Werror=implicit-function-declaration]
             pthread_cancel(s->circular_buffer_thread);


解决方案:修改ffmpeg/libavformat/udp.c文件函数开始部分,添加:

#define SIG_CANCEL_SIGNAL SIGUSR1
#define PTHREAD_CANCEL_ENABLE 1
#define PTHREAD_CANCEL_DISABLE 0

typedef long pthread_t;

static int pthread_setcancelstate(int state, int *oldstate) {
    sigset_t   new, old;
    int ret;
    sigemptyset (&new);
    sigaddset (&new, SIG_CANCEL_SIGNAL);

    ret = pthread_sigmask(state == PTHREAD_CANCEL_ENABLE ? SIG_BLOCK : SIG_UNBLOCK, &new , &old);
    if(oldstate != NULL)
    {
        *oldstate =sigismember(&old,SIG_CANCEL_SIGNAL) == 0 ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE;
    }
    return ret;
}

static inline int pthread_cancel(pthread_t thread) {
    return pthread_kill(thread, SIG_CANCEL_SIGNAL);
}

另:在Android NDK中是没有libpthread.a的,有关的功能实现已经被集成到了libc.a中,所以使用时不需要使用-lpthread,而应该使用-lc链接参数。


附:ffmpeg添加libdavs2模块并合并成一个.so文件输出的arm64版编译脚本:

#!/bin/sh

build_dir=$(pwd)

AVS2SRC=$build_dir/cavs2dec_lib # path to libdavs2 install dictionary
ARCH=arm64
SDK_VERSION=21
NDK="/Android/android-ndk-r14b"

export PKG_CONFIG_PATH=$AVS2SRC/lib/pkgconfig


if [ "$ARCH" = "arm64" ]
then
    PLATFORM_PREFIX="aarch64-linux-android-"
    HOST="aarch64"
    PLATFORM_VERSION=4.9
    EXTRA_CFLAGS="-march=armv8-a -O3 -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -DPIC \
-flax-vector-conversions -Wunused-variable -fPIE -pie -pthread"
else
    PLATFORM_PREFIX="arm-linux-androideabi-"
    HOST="arm"
    PLATFORM_VERSION=4.9
    EXTRA_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon -marm -mtune=cortex-a8 -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ \
-flax-vector-conversions -Wunused-variable -fPIE -pie"
fi

NDKROOT=$NDK/platforms/android-${SDK_VERSION}/arch-${ARCH}
TOOLCHAIN=$NDK/toolchains/${PLATFORM_PREFIX}${PLATFORM_VERSION}/prebuilt/linux-x86_64
CROSS_PREFIX=$TOOLCHAIN/bin/${PLATFORM_PREFIX}
EXTRA_LDFLAGS="-fPIE -pie -llog -landroid -shared"

# cp $NDKROOT/usr/include/linux/sysctl.h $NDKROOT/usr/include/sys/sysctl.h

build_one(){
./configure \
    --target-os=linux \
    --prefix=$build_dir/avs2_lib \
    --enable-cross-compile \
    --extra-libs="-lgcc -lstdc++ -lc" \
    --arch=$ARCH \
    --cross-prefix=$CROSS_PREFIX \
    --cc=${CROSS_PREFIX}gcc \
    --nm=${CROSS_PREFIX}nm \
    --sysroot=$NDKROOT \
    --extra-cflags="-I$NDKROOT/usr/include -I$AVS2SRC/include -O3 -fpic  \
    -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm \
    -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300  \
    -DHAVE_CLOSESOCKET=0 -fvisibility=hidden -fdata-sections -ffunction-sections $EXTRA_CFLAGS" \
    --extra-ldflags="-Wl,-rpath-link=$NDKROOT/usr/lib -L$NDKROOT/usr/lib -lc  \
    -lm -ldl -llog -lstdc++ $AVS2SRC/lib/libdavs2.a -L$AVS2SRC/lib -ldavs2    \
    $EXTRA_LDFLAGS"   \
    --enable-gpl \
    --enable-libdavs2 \
    --disable-shared \
    --enable-static \
    --disable-linux-perf \
    --enable-pic \
    --disable-armv5te \
    --disable-armv6 \
    --disable-armv6t2 \
    --pkg-config=pkg-config 
}

cd FFmpegAVS2

make distclean
build_one
make -j16 && make install

# use to package all part into single .so lib
${CROSS_PREFIX}ld -z muldefs -rpath-link=$NDKROOT/usr/lib \
-L$NDKROOT/usr/lib -L$PREFIX/lib -soname libffmpeg.so -shared -nostdlib -Bsymbolic \
--whole-archive --no-undefined -o $AVS2SRC/libffmpeg.so $AVS2SRC/lib/libdavs2.a  \
libavcodec/libavcodec.a libavfilter/libavfilter.a libswresample/libswresample.a  \
libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a \
libpostproc/libpostproc.a libavdevice/libavdevice.a -fPIC -lc -lm -lz -ldl -llog \
$NDK/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/libgnustl_shared.so -lstdc++ \
--dynamic-linker=/system/bin/linker $TOOLCHAIN/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a

相关文章

网友评论

    本文标题:Android NDK缺失pthread_cancel和pthr

    本文链接:https://www.haomeiwen.com/subject/zkhiiqtx.html