p9fj35fl6/Gazebo_exercise/gazebo7_7.14.0_exercise/gazebo/gazebo_main.cc

203 lines
6.1 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* 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.
*
*/
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include "gazebo/common/Console.hh"
#include "gazebo/Server.hh"
#include "gazebo/gui/GuiIface.hh"
bool sig_killed = false;
int status1, status2;
pid_t pid1, pid2;
bool killed1 = false;
bool killed2 = false;
/////////////////////////////////////////////////
void help()
{
std::cerr << "gazebo -- Run the Gazebo server and GUI.\n\n";
std::cerr << "`gazebo` [options] <world_file>\n\n";
std::cerr << "Gazebo server runs simulation and handles commandline "
<< "options, starts a Master, runs World update and sensor generation "
<< "loops. This also starts the Gazebo GUI client in a separate "
<< "process.\n\n";
std::cerr << "Options:\n"
<< " -v [ --version ] Output version information.\n"
<< " --verbose Increase the messages written to the "
<< "terminal.\n"
<< " -h [ --help ] Produce this help message.\n"
<< " -u [ --pause ] Start the server in a paused state.\n"
<< " -e [ --physics ] arg Specify a physics engine "
<< "(ode|bullet|dart|simbody).\n"
<< " -p [ --play ] arg Play a log file.\n"
<< " -r [ --record ] Record state data.\n"
<< " --record_encoding arg (=zlib) Compression encoding format for log "
<< "data \n"
<< " (zlib|bz2|txt).\n"
<< " --record_path arg Absolute path in which to store "
<< "state data.\n"
<< " --record_period arg (=-1) Recording period (seconds).\n"
<< " --record_filter arg Recording filter (supports wildcard and "
<< "regular expression).\n"
<< " --record_resources Recording with model meshes and "
<< "materials.\n"
<< " --seed arg Start with a given random number seed.\n"
<< " --iters arg Number of iterations to simulate.\n"
<< " --minimal_comms Reduce the TCP/IP traffic output by "
<< "gazebo.\n"
<< " -g [ --gui-plugin ] arg Load a GUI plugin.\n"
<< " -s [ --server-plugin ] arg Load a server plugin.\n"
<< " -o [ --profile ] arg Physics preset profile name from the "
<< "options in\n"
<< " the world file.\n"
<< "\n";
}
/////////////////////////////////////////////////
void sig_handler(int /*signo*/)
{
sig_killed = true;
kill(pid1, SIGINT);
kill(pid2, SIGINT);
double sleepSecs = 0.001;
double totalWaitSecs = 5.0;
// Wait some time and if not dead, escalate to SIGKILL
for (unsigned int i = 0; i < (unsigned int)(totalWaitSecs*1/sleepSecs); ++i)
{
if (!killed1)
{
int p1 = waitpid(pid1, &status1, WNOHANG);
if (p1 == pid1)
killed1 = true;
}
if (!killed2)
{
int p2 = waitpid(pid2, &status2, WNOHANG);
if (p2 == pid2)
killed2 = true;
}
if (killed1 && killed2)
break;
// Sleep briefly
gazebo::common::Time::Sleep(gazebo::common::Time(sleepSecs));
}
if (!killed1)
{
gzwarn << "escalating to SIGKILL on server\n";
kill(pid1, SIGKILL);
}
if (!killed2)
{
gzwarn << "escalating to SIGKILL on client\n";
kill(pid2, SIGKILL);
}
}
/////////////////////////////////////////////////
int main(int _argc, char **_argv)
{
if (_argc >= 2 &&
(strcmp(_argv[1], "-h") == 0 || strcmp(_argv[1], "--help") == 0))
{
help();
return 0;
}
struct sigaction sigact;
sigact.sa_flags = 0;
sigact.sa_handler = sig_handler;
if (sigemptyset(&sigact.sa_mask) != 0)
std::cerr << "sigemptyset failed while setting up for SIGINT" << std::endl;
if (sigaction(SIGINT, &sigact, NULL))
{
gzerr << "Stopping. Unable to catch SIGINT.\n"
<< " Please visit http://gazebosim.org/support.html for help.\n";
return 0;
}
pid1 = fork();
char **argvServer = new char*[_argc+1];
char **argvClient = new char*[_argc+1];
argvServer[0] = const_cast<char*>("gzserver");
argvClient[0] = const_cast<char*>("gzclient");
for (int i = 1; i < _argc; ++i)
{
argvServer[i] = _argv[i];
argvClient[i] = _argv[i];
}
argvServer[_argc] = static_cast<char*>(NULL);
argvClient[_argc] = static_cast<char*>(NULL);
// Need to check the return of wait function (8 lines below) to know
// what should be returned by the process
int returnValue = 0;
if (pid1)
{
pid2 = fork();
if (pid2)
{
int child_exit_status;
pid_t dead_child = wait(&child_exit_status);
// WIFEXITED will return zero if the process finished not reaching
// return or exit calls.
// WEXITSTATUS will check the value of the return function, not being
// zero means problems.
if ((WIFEXITED(child_exit_status) == 0) ||
(WEXITSTATUS(child_exit_status) != 0))
returnValue = -1;
else
returnValue = 0;
if (dead_child == pid1)
killed1 = true;
else if (dead_child == pid2)
killed2 = true;
// one of the children died
if (!sig_killed)
sig_handler(SIGINT);
}
else
{
// gazebo::gui::run(_argc, _argv);
// gzclient argv
execvp(argvClient[0], argvClient);
}
}
else
{
// gazebo::Server *server = new gazebo::Server();
// if (!server->ParseArgs(_argc, _argv))
// return -1;
// server->Run();
// server->Fini();
// delete server;
// server = NULL;
execvp(argvServer[0], argvServer);
}
delete[] argvServer;
delete[] argvClient;
return returnValue;
}