用例
Android C++命令行工具午餐“/ system / bin / getprop”并将其标准输出重定向到套接字
问题
午餐'getprop'失败,并显示“F / libc(20694):致命信号11(SIGSEGV),代码1,tid 20694(getprop)中的故障地址0x0”,代码和logcat代码段。
为什么我得到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()。引用OSX / BSD(但实际上是通用的)execvp()手册页
通过传递一个包含一个NULL元素的数组来破坏此约定,当时,您应将程序名称作为第一个元素传递,然后是一个终止NULL元素。
这将getprop
设置为失败,因为它考虑到只有一个参数(本身)的可能性,在这种情况下它将显示所有内容。
if (argc == 1) {
list_properties();
但是,如果它没有1个参数,则假定它必须有两个或多个,并尝试取消引用第二个参数,该参数应该是您要获取的属性的名称。
property_get(argv[1], value, default_value);
将无效的且可能为空的指针代替属性名传递给property_get()最终会在仿生libc的内部深处失败,这很可能是__system_property_find()的实现调用strlen()的地方。
如果按照建议的方式检查了堆栈跟踪,则可能会在libc中看到一个地址,可能是strlen()。