diff --git a/public-trunk/apps/OpenBTS.config.example b/public-trunk/apps/OpenBTS.config.example index acb6ba9..f308008 100644 --- a/public-trunk/apps/OpenBTS.config.example +++ b/public-trunk/apps/OpenBTS.config.example @@ -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. diff --git a/public-trunk/apps/OpenBTS.cpp b/public-trunk/apps/OpenBTS.cpp index 8e54a71..afb466d 100644 --- a/public-trunk/apps/OpenBTS.cpp +++ b/public-trunk/apps/OpenBTS.cpp @@ -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