我在 google 和 StackOverflow 上搜索了与此类似的任何内容,但最接近的是 C 代码,情况不一样......
我有一个程序通过 cstdlib 的 system() 调用脚本启动另一个程序,一切正常,问题是当我必须测试新代码时,所以我停止执行(Crtl+C 和 kill -9 pid 产生相同的错误),编译新的可执行文件并尝试再次运行它,这时我收到套接字已在使用中的消息。
我的程序使用一个接受器并等待连接(它一次处理一个)。它可以通过一个脚本检索/发送文件并启动/停止另一个程序。如果我只是检索/发送文件,则套接字不会被锁定,但是如果执行了任何 system() 调用,那么套接字就会被锁定,并且在我关闭它后我无法运行该程序。
我真的不认为这与实际的 asio 部分有关,因为它可以正常工作,但这就是我定义端点的方式:
ba::ip::tcp::endpoint endpoint(ba::ip::address_v4::any(), listen_port);
其中 ba 是 boost::asio 的缩写。和 ssl:
ba::ip::tcp::acceptor acceptor_(*io,endpoint);
ba::ssl::context context_(*io, ba::ssl::context::sslv23);
context_.set_options( ba::ssl::context::default_workarounds |
ba::ssl::context::no_sslv2 |
ba::ssl::context::single_dh_use);
//Rest of context config
//Some more code
stream.reset( new ssl_stream(*io,context_) );
boost::system::error_code ec;
boost::system::error_code no_error; // default error_code = no error
while(true)
{
ec = no_error;
stream.reset( new ssl_stream(*io,context_) );
acceptor_.accept(stream->lowest_layer(), endpoint,ec);
if( !ec )
{
stream->handshake(ba::ssl::stream_base::server,ec);
if( !ec )
{
operations();
}
//rest of the code...
}//while(true) end
acceptor_.close();
if(pid == 0)
{
std::cout << "Child exiting!" << std::endl;
}
流在哪里:
boost::shared_ptr< boost::asio::ssl::stream<boost::asio::ip::tcp::socket> > stream;
无论如何,为了更清楚,这是两种情况:
第一:(好的)
# ./program
(Then, I only retrieve/send files)
# kill -9 program_pid ( or Crtl+C)
# g++ .... -o program
# ./program
(Program starts normally)
第二:(错误)
#./program
(Use system() to start other program 1+ times)
# kill -9 program_pid (or Crtl+C)
# g++ .... -o program
# ./program
(Program fails to start, since socket "is already being used")
有趣的事实:
- 如果我重新启动/停止(通过终端)我在我的程序中启动的另一个程序,则释放套接字。
- 即使 fork() -> execv() 相同的命令,也会导致套接字“锁定”。
- 已启动程序的父 PID 为 1,而不是我的程序的 PID...
我想也许另一个程序做错了什么,所以我尝试使用我的系统调用来启动另一个程序(Apache,通过它在 init.d 中的脚本),我得到了相同的结果。
所以我有点迷失在“为什么会发生这种情况”和“我该如何解决这个问题”......
system() 似乎与它有关,但我不知道为什么因为调用返回并且套接字与它无关。即使从子进程(通过 fork())使用 execv() 调用相同的命令也会产生相同的错误......
还没有尝试过popen(),但我相信我会到达同一个地方。
编辑:刚刚意识到 system() 实际上是一个 fork() 后跟一个 exec,所以没有必要指出这一点......
EDIT2:添加更多细节
按照 Tanner Sansbury 的回答,我更改了代码,但结果仍然相同......
关于操作我只是阅读了操作并调用了相关的函数。
然后我落在我的功能上:
//Function body:
if (this->existBinary())
{
io->notify_fork(boost::asio::io_service::fork_prepare);
pid = fork();
if( pid == 0 )
{
io->notify_fork(boost::asio::io_service::fork_child);
char binChar[80];
for(unsigned int i = 0; i < bin.size(); ++i)
{
binChar[i] = bin[i];
}
binChar[bin.size()] = '\0';
char* bin_args[] = { binChar, "start" , NULL };
execv( bin_args[0], bin_args );
}
else
{
io->notify_fork(boost::asio::io_service::fork_parent);
if( pid == -1)
{
std::cout << "Fork error" << std::endl;
}
else
{
// running in parent, wait exec to complete
// and return its exit status.
int status;
waitpid( pid, &status, 0 );
printf("Child %d exited with status %d\n", pid, status );
}
}
// returning true just for testing
return true;
}
return false;
existsBinary() 函数:
bool my_class::existBinary(const std::string& filename) const
{
std::ifstream file(filename.c_str(),std::ios_base::in | std::ios_base::binary);
bool file_status = false;
if(file.is_open())
{
file_status = true;
file.close();
}
return file_status;
}
请注意,当孩子退出时,我放了一个 cout 来打印,但它什么也没显示...... :(
我将尝试将接受者移动为班级成员并将其关闭在孩子身上。
同样,当我重新启动/停止其他程序时,套接字被释放......