Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release exclusive access to serial port on close #190

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 40 additions & 12 deletions src/SerialPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,15 @@ namespace LibSerial
* @param parityType The parity type for the serial port.
* @param stopBits The number of stop bits for the serial port.
* @param flowControlType The flow control type for the serial port.
* @param exclusive Set exclusive access for the serial port.
*/
Implementation(const std::string& fileName,
const BaudRate& baudRate,
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits) ;
const StopBits& stopBits,
bool exclusive) ;

/**
* @brief Default Destructor for a SerialPort object. Closes the
Expand Down Expand Up @@ -110,9 +112,11 @@ namespace LibSerial
* @param fileName The file name of the serial port.
* @param openMode The communication mode status when the serial
* communication port is opened.
* @param exclusive Set exclusive access for this serial port.
*/
void Open(const std::string& fileName,
const std::ios_base::openmode& openMode) ;
const std::ios_base::openmode& openMode,
bool exclusive) ;

/**
* @brief Closes the serial port. All settings of the serial port will be
Expand Down Expand Up @@ -466,6 +470,12 @@ namespace LibSerial
*/
int mByteArrivalTimeDelta = 1 ;

/**
* Whether the process that opened the serial port has exclusive
* access to it.
*/
bool mExclusiveAccess = true;

/**
* Serial port settings are saved into this struct immediately after
* the port is opened. These settings are restored when the serial port
Expand All @@ -485,13 +495,15 @@ namespace LibSerial
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits)
const StopBits& stopBits,
bool exclusive)
: mImpl(new Implementation(fileName,
baudRate,
characterSize,
flowControlType,
parityType,
stopBits))
stopBits,
exclusive))
{
/* Empty */
}
Expand All @@ -512,10 +524,12 @@ namespace LibSerial

void
SerialPort::Open(const std::string& fileName,
const std::ios_base::openmode& openMode)
const std::ios_base::openmode& openMode,
bool exclusive)
{
mImpl->Open(fileName,
openMode) ;
openMode,
exclusive) ;
}

void
Expand Down Expand Up @@ -809,9 +823,10 @@ namespace LibSerial
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits)
const StopBits& stopBits,
bool exclusive)
{
this->Open(fileName, std::ios_base::in | std::ios_base::out) ;
this->Open(fileName, std::ios_base::in | std::ios_base::out, exclusive) ;
this->SetBaudRate(baudRate) ;
this->SetCharacterSize(characterSize) ;
this->SetFlowControl(flowControlType) ;
Expand Down Expand Up @@ -843,7 +858,8 @@ namespace LibSerial
inline
void
SerialPort::Implementation::Open(const std::string& fileName,
const std::ios_base::openmode& openMode)
const std::ios_base::openmode& openMode,
bool exclusive)
{
// Throw an exception if the port is already open.
if (this->IsOpen())
Expand Down Expand Up @@ -885,9 +901,10 @@ namespace LibSerial

// Set the serial port to exclusive access to this process.
// NOLINTNEXTLINE (cppcoreguidelines-pro-type-vararg)
if (call_with_retry(ioctl,
this->mFileDescriptor,
TIOCEXCL) == -1)
mExclusiveAccess = exclusive;
if (mExclusiveAccess && call_with_retry(ioctl,
this->mFileDescriptor,
TIOCEXCL) == -1)
{
throw std::runtime_error(std::strerror(errno)) ;
}
Expand Down Expand Up @@ -935,6 +952,17 @@ namespace LibSerial
err_msg = std::strerror(errno) ;
}

// Release the serial port from exclusive access.
if (mExclusiveAccess)
{
// NOLINTNEXTLINE (cppcoreguidelines-pro-type-vararg)
if(call_with_retry(ioctl, this->mFileDescriptor, TIOCNXCL) == -1)
{
err_msg += ", ";
err_msg += std::strerror(errno);
}
}

// Otherwise, close the serial port and set the file descriptor
// to an invalid value.
bool is_failed = false ;
Expand Down
10 changes: 6 additions & 4 deletions src/SerialStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ namespace LibSerial
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits) :
const StopBits& stopBits,
bool exclusive) :
std::iostream(nullptr)
{
this->Open(fileName) ; // NOLINT (fuchsia-default-arguments)
this->Open(fileName, std::ios_base::in | std::ios_base::out, exclusive) ; // NOLINT (fuchsia-default-arguments)
this->SetBaudRate(baudRate) ;
this->SetCharacterSize(characterSize) ;
this->SetFlowControl(flowControlType) ;
Expand Down Expand Up @@ -81,7 +82,8 @@ namespace LibSerial

void
SerialStream::Open(const std::string& fileName,
const std::ios_base::openmode& openMode)
const std::ios_base::openmode& openMode,
bool exclusive)
try
{
// Create a new SerialStreamBuf if one does not exist.
Expand All @@ -93,7 +95,7 @@ namespace LibSerial
}

// Open the serial port.
mIOBuffer->Open(fileName, openMode) ;
mIOBuffer->Open(fileName, openMode, exclusive) ;
}
catch (const std::exception&)
{
Expand Down
32 changes: 22 additions & 10 deletions src/SerialStreamBuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,15 @@ namespace LibSerial
* @param parityType The parity type for the serial stream.
* @param stopBits The number of stop bits for the serial stream.
* @param flowControlType The flow control type for the serial stream.
* @param exclusive Set exclusive access for the serial stream.
*/
Implementation(const std::string& fileName,
const BaudRate& baudRate,
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits) ;
const StopBits& stopBits,
bool exclusive) ;

/**
* @brief Copy construction is disallowed.
Expand Down Expand Up @@ -103,9 +105,11 @@ namespace LibSerial
* @param fileName The file name of the serial port.
* @param openMode The communication mode status when the serial
* communication port is opened.
* @param exclusive Set exclusive access for this serial port.
*/
void Open(const std::string& fileName,
const std::ios_base::openmode& openMode) ;
const std::ios_base::openmode& openMode,
bool exclusive) ;

/**
* @brief Closes the serial port. All settings of the serial port will be
Expand Down Expand Up @@ -390,13 +394,15 @@ namespace LibSerial
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits)
const StopBits& stopBits,
bool exclusive)
: mImpl(new Implementation(fileName,
baudRate,
characterSize,
flowControlType,
parityType,
stopBits))
stopBits,
exclusive))
{
setbuf(nullptr, 0) ;
}
Expand All @@ -405,10 +411,12 @@ namespace LibSerial

void
SerialStreamBuf::Open(const std::string& fileName,
const std::ios_base::openmode& openMode)
const std::ios_base::openmode& openMode,
bool exclusive)
{
mImpl->Open(fileName,
openMode) ;
openMode,
exclusive) ;
}

void
Expand Down Expand Up @@ -656,13 +664,15 @@ namespace LibSerial
const CharacterSize& characterSize,
const FlowControl& flowControlType,
const Parity& parityType,
const StopBits& stopBits)
const StopBits& stopBits,
bool exclusive)
try : mSerialPort(fileName,
baudRate,
characterSize,
flowControlType,
parityType,
stopBits)
stopBits,
exclusive)
{
// empty
}
Expand Down Expand Up @@ -695,11 +705,13 @@ namespace LibSerial
inline
void
SerialStreamBuf::Implementation::Open(const std::string& fileName,
const std::ios_base::openmode& openMode)
const std::ios_base::openmode& openMode,
bool exclusive)
try
{
mSerialPort.Open(fileName,
openMode) ;
openMode,
exclusive) ;

// @note - Stream communications need to happen in blocking mode.
mSerialPort.SetSerialPortBlockingStatus(true) ;
Expand Down
8 changes: 6 additions & 2 deletions src/libserial/SerialPort.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ namespace LibSerial
* @param parityType The parity type for the serial port.
* @param stopBits The number of stop bits for the serial port.
* @param flowControlType The flow control type for the serial port.
* @param exclusive Set exclusive access for the serial port.
*/
explicit SerialPort(const std::string& fileName,
const BaudRate& baudRate = BaudRate::BAUD_DEFAULT,
const CharacterSize& characterSize = CharacterSize::CHAR_SIZE_DEFAULT,
const FlowControl& flowControlType = FlowControl::FLOW_CONTROL_DEFAULT,
const Parity& parityType = Parity::PARITY_DEFAULT,
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT) ;
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT,
bool exclusive = true) ;

/**
* @brief Default Destructor for a SerialPort object. Closes the
Expand Down Expand Up @@ -112,9 +114,11 @@ namespace LibSerial
* @param fileName The file name of the serial port.
* @param openMode The communication mode status when the serial
* communication port is opened.
* @param exclusive Set exclusive access for the serial port.
*/
void Open(const std::string& fileName,
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out) ;
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out,
bool exclusive = true) ;

/**
* @brief Closes the serial port. All settings of the serial port will be
Expand Down
9 changes: 7 additions & 2 deletions src/libserial/SerialStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,15 @@ namespace LibSerial
* @param parityType The parity type for the serial stream.
* @param stopBits The number of stop bits for the serial stream.
* @param flowControlType The flow control type for the serial stream.
* @param exclusive Set exclusive access for the serial stream.
*/
explicit SerialStream(const std::string& fileName,
const BaudRate& baudRate = BaudRate::BAUD_DEFAULT,
const CharacterSize& characterSize = CharacterSize::CHAR_SIZE_DEFAULT,
const FlowControl& flowControlType = FlowControl::FLOW_CONTROL_DEFAULT,
const Parity& parityType = Parity::PARITY_DEFAULT,
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT) ;
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT,
bool exclusive = true) ;

/**
* @brief Default Destructor for a SerialStream object
Expand Down Expand Up @@ -140,9 +142,12 @@ namespace LibSerial
* @param fileName The file name of the serial port.
* @param openMode The communication mode status when the serial
* communication port is opened.
* @param exclusive Set exclusive access for this process to the
* serial port.
*/
void Open(const std::string& fileName,
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out) ;
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out,
bool exclusive = true) ;

/**
* @brief Closes the serial port. All settings of the serial port will be
Expand Down
9 changes: 7 additions & 2 deletions src/libserial/SerialStreamBuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,15 @@ namespace LibSerial
* @param parityType The parity type for the serial stream.
* @param stopBits The number of stop bits for the serial stream.
* @param flowControlType The flow control type for the serial stream.
* @param exclusive Set exclusive access for the serial stream
*/
explicit SerialStreamBuf(const std::string& fileName,
const BaudRate& baudRate = BaudRate::BAUD_DEFAULT,
const CharacterSize& characterSize = CharacterSize::CHAR_SIZE_DEFAULT,
const FlowControl& flowControlType = FlowControl::FLOW_CONTROL_DEFAULT,
const Parity& parityType = Parity::PARITY_DEFAULT,
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT) ;
const StopBits& stopBits = StopBits::STOP_BITS_DEFAULT,
bool exclusive = true) ;

/**
* @brief Default Destructor for a SerialStreamBuf object. Closes the
Expand Down Expand Up @@ -115,9 +117,12 @@ namespace LibSerial
* @param fileName The file name of the serial port.
* @param openMode The communication mode status when the serial
* communication port is opened.
* @param exclusive Set exclusive access for this process to the
* serial port.
*/
void Open(const std::string& fileName,
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out) ;
const std::ios_base::openmode& openMode = std::ios_base::in | std::ios_base::out,
bool exclusive = true) ;

/**
* @brief Closes the serial port. All settings of the serial port will be
Expand Down