Android,CMDTool,标准输出重定向, "Fatal signal 11 (SIGSEGV)"

标签 android c++ linux android-ndk android-source

用例

Android C++ 命令行工具启动“/system/bin/getprop”并将其标准输出重定向到套接字

问题

“getprop”午餐失败,显示“F/libc (20694):致命信号 11 (SIGSEGV),代码 1,tid 20694 (getprop) 中的故障地址 0x0”,代码和 logcat fragment 如下。

为什么我会收到 SIGSEGV?为什么 fork 进程失败?

实现

HRESULT ServiceCore::CreateProcessAndRedirectStdout(IN char* pCmd, IN char** args, OUT SOCKET& stdoutstream) {
    HRESULT hr      = S_OK;
    int     fds[2]  = { 0 };
    pid_t   pid     = 0;
    stdoutstream = 0;
    if (SOCKET_ERROR == socketpair(PF_UNIX, SOCK_STREAM, 0, fds))
        goto ErrExit;
    stdoutstream = fds[1];
    if((pid = fork()) < 0)
        goto ErrExit;
    if (pid == 0) {
        // The newly created process
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' started", pCmd);
        int newfd = dup2(fds[0], STDOUT_FILENO);
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' newfd:%d, oldfd:%d", pCmd, newfd, fds[0]);
        _ASSERT(newfd == STDOUT_FILENO);

        close(fds[0]);
        close(fds[1]);
        execvp(pCmd, args);
        __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s' FAILED", pCmd);
        exit(1);
    }
    __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "CreateProcessAndRedirectStdout>> '%s(%d)' Created", pCmd, pid);
    return S_OK;
ErrExit:
    if (0 != pid)
        kill(pid, SIGTERM);
    close(fds[0]);
    close(fds[1]);
    stdoutstream = 0;
    return hr;
}

...
        char* args[] = { 0 };
        SOCKET soc;
        if (SUCCEEDED(hr = CreateProcessAndRedirectStdout("/system/bin/getprop", args, soc))) {
            errno = 0;
            __android_log_print(ANDROID_LOG_INFO, "ServiceCore", "SendConfig>> Reading props");
            char pTmp[256000];
            int iRet = read(soc, pTmp, sizeof(pTmp));// Read the first few lines
        }

...

日志

I/ServiceCore(20689): CreateProcessAndRedirectStdout>> '/system/bin/getprop(20694)' Created

I/ServiceCore(20689): SendConfig>> Reading props

I/ServiceCore(20694): CreateProcessAndRedirectStdout>> '/system/bin/getprop' started

I/ServiceCore(20694): CreateProcessAndRedirectStdout>> '/system/bin/getprop' newfd:1, oldfd:10

F/libc    (20694): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 20694 (getprop)

最佳答案

您以 getprop 未编写处理的方式滥用 execvp()。引用 execvp() 的 OSX/BSD(但实际上是通用的)手册页

The execv(), execvp(), and execvP() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the file name associated with the file being executed. The array of pointers must be terminated by a NULL pointer.

您应该将程序的名称作为第一个元素传递,然后是一个终止的 NULL 元素时,您通过传递一个 NULL 元素的数组来打破这个约定。

这将 getprop 设置为失败,因为它考虑到只有一个参数(它本身)的可能性,在这种情况下它将显示所有内容。

    if (argc == 1) {
        list_properties();

但如果它没有 1 个参数,它假设它必须有两个或更多,并尝试取消引用第二个参数,应该是名称您想获得的属性(property)。

    property_get(argv[1], value, default_value);

将无效且可能为空的指针代替属性名称传递给 property_get() 最终会在仿生 libc 的深处失败,可能是在 __system_property_find() 的实现调用 strlen() 的地方。

如果您按照 fadden 的建议检查堆栈跟踪,您可能会在 libc 中看到一个地址,可能是 strlen()。

关于Android,CMDTool,标准输出重定向, "Fatal signal 11 (SIGSEGV)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28557915/

相关文章:

linux - 未生成绘图(来自命令行的 gnuplot)

android - Android Camera Client 的优先级是如何设置的?

c++ - gcc MinGW 上的 InterlockedOr8

C++ STL 二进制搜索(lower_bound,upper_bound)

linux - 什么是/dev/mapper/vg_root-lv_root 目录?为什么我的 docker 依赖这个目录?

php - 使用 php 创建 linux 用户?

java - 我如何在 Skype 上玩 google?

java - 类转换异常 : MainActivity cannot be cast to Listener

android - 后台服务限制和 Firebase 云消息传递

c++ - 适配器模式