Commit cb054071 authored by Zhangyi Chen's avatar Zhangyi Chen

Add missing file needed by 79f2e7d3

parent 79f2e7d3
// Copyright (c) 2017 Baidu.com, Inc. All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: Zhangyi Chen (chenzhangyi01@baidu.com)
// Date: 2017/11/04 17:37:43
#include "butil/build_config.h"
#include "butil/logging.h"
#if defined(OS_LINUX)
// clone is a linux specific syscall
#include <sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
extern "C" {
uint64_t BAIDU_WEAK bthread_usleep(uint64_t microseconds);
}
namespace butil {
const int CHILD_STACK_SIZE = 64 * 1024;
struct ChildArgs {
const char* cmd;
int pipe_fd0;
int pipe_fd1;
};
int launch_child_process(void* args) {
ChildArgs* cargs = (ChildArgs*)args;
dup2(cargs->pipe_fd1, STDOUT_FILENO);
close(cargs->pipe_fd0);
close(cargs->pipe_fd1);
execl("/bin/sh", "sh", "-c", cargs->cmd, NULL);
_exit(1);
}
int read_command_output(std::ostream& os, const char* cmd) {
int pipe_fd[2];
if (pipe(pipe_fd) != 0) {
PLOG(ERROR) << "Fail to pipe";
return -1;
}
int saved_errno = 0;
int wstatus = 0;
pid_t cpid;
int rc = 0;
ChildArgs args = { cmd, pipe_fd[0], pipe_fd[1] };
char buffer[1024];
char* child_stack = NULL;
char* child_stack_mem = (char*)malloc(CHILD_STACK_SIZE);
if (!child_stack_mem) {
LOG(ERROR) << "Fail to alloc stack for the child process";
rc = -1;
goto END;
}
child_stack = child_stack_mem + CHILD_STACK_SIZE;
// ^ Assume stack grows downward
cpid = clone(launch_child_process, child_stack,
__WCLONE | CLONE_VM | SIGCHLD, &args);
if (cpid < 0) {
PLOG(ERROR) << "Fail to clone child process";
rc = -1;
goto END;
}
close(pipe_fd[1]);
pipe_fd[1] = -1;
for (;;) {
const ssize_t nr = read(pipe_fd[0], buffer, sizeof(buffer));
if (nr > 0) {
os.write(buffer, nr);
continue;
} else if (nr == 0) {
break;
} else if (errno != EINTR) {
LOG(ERROR) << "Encountered error while reading for the pipe";
break;
}
}
close(pipe_fd[0]);
pipe_fd[0] = -1;
for (;;) {
pid_t wpid = waitpid(cpid, &wstatus, WNOHANG);
if (wpid > 0) {
break;
}
if (wpid == 0) {
if (bthread_usleep != NULL) {
bthread_usleep(1000);
} else {
usleep(1000);
}
continue;
}
rc = -1;
goto END;
}
if (WIFEXITED(wstatus)) {
rc = WEXITSTATUS(wstatus);
goto END;
}
if (WIFSIGNALED(wstatus)) {
os << "Child process(" << cpid << ") was killed by signal "
<< WTERMSIG(wstatus);
}
rc = -1;
errno = ECHILD;
END:
saved_errno = errno;
if (child_stack_mem) {
free(child_stack_mem);
}
if (pipe_fd[0] >= 0) {
close(pipe_fd[0]);
}
if (pipe_fd[1] >= 0) {
close(pipe_fd[1]);
}
errno = saved_errno;
return rc;
}
} // namespace butil
#else // OS_LINUX
#include <stdio.h>
namespace butil {
int read_command_output(std::ostream& os, const char* cmd) {
FILE* pipe = popen(cmd, "r");
if (pipe == NULL) {
return -1;
}
char buffer[1024];
for (;;) {
size_t nr = fread(buffer, 1, sizeof(buffer), pipe);
if (nr != 0) {
os.write(buffer, nr);
}
if (nr != sizeof(buffer)) {
if (feof(pipe)) {
break;
} else if (ferror(pipe)) {
LOG(ERROR) << "Encountered error while reading for the pipe";
break;
}
// retry;
}
}
return pclose(pipe);
}
} // namespace butil
#endif // OS_LINUX
// Copyright (c) 2017 Baidu.com, Inc. All Rights Reserved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Author: Zhangyi Chen (chenzhangyi01@baidu.com)
// Date: 2017/11/04 17:13:18
#ifndef PUBLIC_COMMON_POPEN_H
#define PUBLIC_COMMON_POPEN_H
#include <ostream>
namespace butil {
// Read the stdout of child process executing `cmd'.
// Returns the exit status(0-255) of cmd and all the output is stored in
// |os|. -1 otherwise and errno is set appropriately.
int read_command_output(std::ostream& os, const char* cmd);
}
#endif //PUBLIC_COMMON_POPEN_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment