laforge
/
openbts-osmo
Archived
1
0
Fork 0

Save transceiver PID to a file and use it to kill old transceivers.

This commit is contained in:
Alexander Chemeris 2010-11-23 12:01:21 +03:00 committed by Thomas Tsou
parent 1cd7f00470
commit 7b3c0d3090
2 changed files with 97 additions and 30 deletions

View File

@ -118,6 +118,14 @@ TRX.Path ../Transceiver/transceiver
#TRX.Path ../Transceiver52M/transceiver
$static TRX.Path
# Path to transceiver PID file.
# Filesystem Hierarchy Standard specifies it daemons should write PID
# to /var/run, but you may specify any other directory if you run
# OpenBTS manually.
#TRX.WritePID /var/run/transceiver.pid
TRX.WritePID transceiver.pid
$static TRX.WritePID
# TRX logging.
# Logging level.
# IF TRX.Path IS DEFINED, THIS MUST ALSO BE DEFINED.

View File

@ -117,21 +117,94 @@ void shutdownOpenbts()
{
kill(SIGTERM, getpid());
}
static int openPidFile(const std::string &lockfile)
{
int lfp = open(lockfile.data(), O_RDWR|O_CREAT, 0640);
if (lfp < 0) {
LOG(ERROR) << "Unable to create PID file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
} else {
LOG(INFO) << "Created PID file " << lockfile;
}
return lfp;
}
static void restartTransceiver()
static int lockPidFile(const std::string &lockfile, int lfp, bool block=false)
{
// This is harmless - if someone is running OpenBTS they WANT no transceiver
// instance at the start anyway.
if (sgTransceiverPid > 0) {
LOG(INFO) << "RESTARTING TRANSCEIVER";
kill(sgTransceiverPid,SIGKILL);
if (lockf(lfp, block?F_LOCK:F_TLOCK,0) < 0) {
LOG(ERROR) << "Unable to lock PID file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int writePidFile(const std::string &lockfile, int lfp, int pid)
{
// Clear old file content first
if (ftruncate(lfp, 0) < 0) {
LOG(ERROR) << "Unable to clear PID file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
// Write PID
char tempBuf[64];
snprintf(tempBuf, sizeof(tempBuf), "%d\n", pid);
ssize_t tempDataLen = strlen(tempBuf);
lseek(lfp, 0, SEEK_SET);
if (write(lfp, tempBuf, tempDataLen) != tempDataLen) {
LOG(ERROR) << "Unable to write PID to file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int readPidFile(const std::string &lockfile, int lfp, int &pid)
{
char tempBuf[64];
lseek(lfp, 0, SEEK_SET);
int bytesRead = read(lfp, tempBuf, sizeof(tempBuf));
if (bytesRead <= 0) {
LOG(ERROR) << "Unable to read PID from file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
tempBuf[bytesRead<sizeof(tempBuf)?bytesRead:sizeof(tempBuf)-1] = '\0';
int res = sscanf(tempBuf, " %d", &pid);
if (res < 1) {
LOG(ERROR) << "Unable to parse PID from file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static int startTransceiver()
{
// Start the transceiver binary, if the path is defined.
// If the path is not defined, the transceiver must be started by some other process.
const char *TRXPath = NULL;
if (gConfig.defines("TRX.Path")) TRXPath=gConfig.getStr("TRX.Path");
if (TRXPath) {
if (gConfig.defines("TRX.Path")) {
// Open and lock PID file, taking care of old transceiver instance.
std::string lockfile = gConfig.getStr("TRX.WritePID");
int lfp = openPidFile(lockfile);
if (lfp < 0) return EXIT_SUCCESS;
int pid;
if (lockPidFile(lockfile, lfp, false) != EXIT_SUCCESS) {
// Another OpenBTS instance is running and blocking PID file.
return EXIT_FAILURE;
}
if (readPidFile(lockfile, lfp, pid) == EXIT_SUCCESS) {
// There is no harm in this. Transceiver's owner is not
// running and could safely kill it.
kill(pid, SIGTERM);
}
// Start transceiver
const char *TRXPath = gConfig.getStr("TRX.Path");
const char *TRXLogLevel = gConfig.getStr("TRX.LogLevel");
const char *TRXLogFileName = NULL;
if (gConfig.defines("TRX.LogFileName")) TRXLogFileName=gConfig.getStr("TRX.LogFileName");
@ -143,7 +216,10 @@ static void restartTransceiver()
LOG(ERROR) << "cannot start transceiver";
_exit(0);
}
// Now we can finally write transceiver PID to the file.
if (writePidFile(lockfile, lfp, sgTransceiverPid) != EXIT_SUCCESS) return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
static void exitCLI()
@ -220,13 +296,7 @@ static int daemonize(std::string &lockfile, int &lfp)
lockfile = gConfig.getStr("Server.WritePID");
// Create the PID file as the current user
lfp = open(lockfile.data(), O_RDWR|O_CREAT, 0640);
if (lfp < 0) {
LOG(ERROR) << "Unable to create PID file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
LOG(INFO) << "Created PID file " << lockfile;
if ((lfp=openPidFile(lockfile)) < 0) return EXIT_FAILURE;
// Drop user if there is one, and we were run as root
/* if ( getuid() == 0 || geteuid() == 0 ) {
@ -266,19 +336,8 @@ static int daemonize(std::string &lockfile, int &lfp)
}
// Now lock our PID file and write our PID to it
if (lockf(lfp, F_TLOCK,0) < 0) {
LOG(ERROR) << "Unable to lock PID file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
char tempBuf[64];
snprintf(tempBuf, sizeof(tempBuf), "%d\n", getpid());
ssize_t tempDataLen = strlen(tempBuf);
if (write(lfp, tempBuf, tempDataLen) != tempDataLen) {
LOG(ERROR) << "Unable to wite PID to file " << lockfile << ", code="
<< errno << " (" << strerror(errno) << ")";
return EXIT_FAILURE;
}
if (lockPidFile(lockfile, lfp) != EXIT_SUCCESS) return EXIT_FAILURE;
if (writePidFile(lockfile, lfp, getpid()) != EXIT_SUCCESS) return EXIT_FAILURE;
// At this point we are executing as the child process
pid_t parent = getppid();
@ -360,7 +419,7 @@ int main(int argc, char *argv[])
LOG(ALARM) << "OpenBTS starting, ver " << VERSION << " build date " << __DATE__;
restartTransceiver();
startTransceiver();
// Start the SIP interface.
gSIPInterface.start();