我正在开发一个项目,需要在Docker容器内执行一些进程。我希望处理在规定时间(比如10秒内)内未能终止的进程。
为管理容器,我使用DockerClientpp库,它基本上只是向Docker套接字发出HTTP请求,到这里都很顺利。
为了停止长时间运行的容器,我使用了一个单独的线程。问题是,我可以使用pthreads实现它,但我无法找到使用std::thread和lambas的方法。
下面是我的工作实现代码,使用了pthread:
void *ContainerManager::spawnKiller(void *ref) {
ContainerManager *self = (ContainerManager *)ref;
std::unique_ptr<DockerClientpp::DockerClient> dc(new DockerClientpp::DockerClient());
std::cout << "[slave]forceStop(): Waiting " << self->timeOut << " before stopping " << self->activeId << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(self->timeOut));
try {
dc->stopContainer(self->activeId);
std::cout << "[slave]forceStop(): Container will be force-stopped" << std::endl;
} catch(std::exception &e) {
// container has already been destroyed
std::cout << "[slave]forceStop(): Error => " << e.what() << std::endl;
}
pthread_exit(0);
}
void ContainerManager::execute() {
pthread_t killerId;
pthread_create(&killerId, nullptr, &(ContainerManager::spawnKiller), (void *)this);
pthread_detach(killerId);
}
这是我的std::thread和lambda实现,当我尝试分离线程时,会出现SEGFAULT错误。
void ContainerManager::execute() {
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(timeOut));
try {
dc->stopContainer(activeId);
std::cout << "[slave]forceStop(): Container will be force-stopped" << std::endl;
} catch(std::exception &e) {
// container has already been destroyed
std::cout << "[slave]forceStop(): Error => " << e.what() << std::endl;
}
}).detach();
}
这是gdb显示的内容。
Thread 1 "test" received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x00000000007c6801 in std::thread::detach() ()
#2 0x0000000000410785 in ContainerManager::execute (this=0x7fffffffe2a0, processName=...)
at ../container_manager.cpp:223
#3 0x0000000000412c99 in ContainerManager::executeNew (this=0x7fffffffe2a0, processName=...,
replace=false, language=@0x7fffffffe020: ContainerManager::GO) at ../container_manager.cpp:336
#4 0x00000000004094a9 in main () at test.cpp:36
我尝试使用普通函数而非lambda,我尝试捕获参数,也尝试将参数作为参数传递,但都卡住了。
我还没有尝试使用new thread(...)
动态分配线程,但从我的理解来看,即使std::thread
变量超出范围,该线程仍然存在。
你有什么建议吗?我觉得我对std::thread和lambda有些重要的东西还不太懂。
execute方法是ContainerManager类的一个方法,在新线程结束之前保证不会超出作用域,我使用的变量(timeOut
和activeId
是对象的字段)。
编辑:
detach()
似乎真的出了点问题。
如果我运行这个
void ContainerManager::execute() {
int *t = new int;
*t = timeOut;
std::string *s = new std::string;
*s = activeId;
std::thread x([&t, &s]() {
std::cout << "LOL" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(*t));
std::unique_ptr<DockerClientpp::DockerClient> _dc(new DockerClientpp::DockerClient());
try {
_dc->stopContainer(*s);
std::cout << "[slave]forceStop(): Container will be force-stopped" << std::endl;
} catch(std::exception &e) {
// container has already been destroyed
std::cout << "[slave]forceStop(): Error => " << e.what() << std::endl;
}
});
std::cout << "Detaching" << std::endl;
if(x.joinable()) {
std::cout << ".. in a moment" << std::endl;
x.detach();
}
}
我收到了这个输出。
Detaching
.. in a moment
Segmentation fault (core dumped)
编辑2 我尝试在我的笔记本电脑上运行这段代码,一切都正常。
void ContainerManager::execute() {
// activeId and timeOut are fields of the ContainerManager object
std::thread([this]() {
std::this_thread::sleep_for(std::chrono::seconds(timeOut));
std::unique_ptr<DockerClientpp::DockerClient> dc(new DockerClientpp::DockerClient());
try {
dc->stopContainer(activeId);
std::cout << "[slave]forceStop(): Container will be force-stopped" << std::endl;
} catch(std::exception &e) {
// container has already been destroyed
std::cout << "[slave]forceStop(): Error => " << e.what() << std::endl;
}
}).detach();
}
dc
被分配,而在 pthreads 版本中,它被线程专门分配。 - selbiedocker run -d ubuntu:14.04 /my/process
,将其替换为docker run -d ubuntu:14.04 timeout 10s /my/process
是否可行?它甚至会返回错误代码124告诉你进程超时了。 - root