From d9e722e1469d27bd32b62baf10999f0c865401ab Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Tue, 6 Oct 2015 16:06:40 +0200
Subject: [PATCH 01/16] Remove redundant gcc debug option from CMakeList.txt
[Feature] N/A
[Cause] N/A
[Solution] N/A
[Verification] Build
Change-Id: I400ad9d6c91560d18d90a3d09d1ee656b4a31948
---
CMakeLists.txt | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0409167..0bd22e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,14 +57,14 @@ else()
SET(CXX_11_STD "c++11")
endif()
-SET(CMAKE_C_FLAGS_PROFILING "-g -O0 -pg")
-SET(CMAKE_CXX_FLAGS_PROFILING "-g -std=${CXX_11_STD} -O0 -pg")
-SET(CMAKE_C_FLAGS_DEBUG "-g -O0 -ggdb")
-SET(CMAKE_CXX_FLAGS_DEBUG "-g -std=${CXX_11_STD} -O0 -ggdb")
-SET(CMAKE_C_FLAGS_RELEASE "-g -O2 -DNDEBUG")
-SET(CMAKE_CXX_FLAGS_RELEASE "-g -std=${CXX_11_STD} -O2 -DNDEBUG")
-SET(CMAKE_C_FLAGS_CCOV "-g -O0 --coverage")
-SET(CMAKE_CXX_FLAGS_CCOV "-g -std=${CXX_11_STD} -O0 --coverage")
+SET(CMAKE_C_FLAGS_PROFILING "-O0 -pg")
+SET(CMAKE_CXX_FLAGS_PROFILING "-std=${CXX_11_STD} -O0 -pg")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -ggdb")
+SET(CMAKE_CXX_FLAGS_DEBUG "-std=${CXX_11_STD} -O0 -ggdb")
+SET(CMAKE_C_FLAGS_RELEASE "-O2 -DNDEBUG")
+SET(CMAKE_CXX_FLAGS_RELEASE "-std=${CXX_11_STD} -O2 -DNDEBUG")
+SET(CMAKE_C_FLAGS_CCOV "-O0 --coverage")
+SET(CMAKE_CXX_FLAGS_CCOV "-std=${CXX_11_STD} -O0 --coverage")
IF(DEFINED SANITIZE)
# Enable sanitize build.
--
2.7.4
From 89486aaa187165127629f9d07b52d0d129132902 Mon Sep 17 00:00:00 2001
From: Pawel Kubik
Date: Fri, 18 Sep 2015 15:03:33 +0200
Subject: [PATCH 02/16] IPC unit tests and testing framework improvements
[Feature] 1. IPC unit tests
2. Cleaner args parsing in vsm_launch_test.py
3. Options to launch a test under custom tools
[Cause] 1. N/A
2. Bugs when launching with external tool
3. Ability to launch any GDB front-end
[Solution] 1. N/A
2. Use list instead of string in Popen
3. Two new command line options
[Verification] Build, install run tests. Try to run single test with
a fixture, for example:
vsm_launch_test.py vasum-server-unit-tests -t \
'IPCSuite/Restart<15ThreadedFixture>'
To test running with --gdb option run test logged as
root or use sudo with -E option in order to preserve
environment.
Change-Id: Icb09c0abed5c671c86a8c85d2aab1aa2b2412d29
---
common/utils/eventfd.cpp | 2 +-
common/utils/exception.hpp | 5 ++
libs/ipc/exception.hpp | 19 +++++
libs/ipc/internals/processor.cpp | 2 +-
libs/ipc/internals/socket.cpp | 4 +-
libs/ipc/unique-id.cpp | 4 +-
tests/scripts/vsm_launch_test.py | 32 +++----
tests/unit_tests/ipc/ut-ipc.cpp | 149 +++++++++++++++++++++++----------
tests/unit_tests/ipc/ut-unique-id.cpp | 19 +++++
tests/unit_tests/utils/ut-fd-utils.cpp | 51 +++++++++++
10 files changed, 219 insertions(+), 68 deletions(-)
create mode 100644 tests/unit_tests/utils/ut-fd-utils.cpp
diff --git a/common/utils/eventfd.cpp b/common/utils/eventfd.cpp
index bc5e64a..627b773 100644
--- a/common/utils/eventfd.cpp
+++ b/common/utils/eventfd.cpp
@@ -42,7 +42,7 @@ EventFD::EventFD()
if (mFD == -1) {
const std::string msg = "Error in eventfd: " + getSystemErrorMessage();
LOGE(msg);
- throw UtilsException(msg);
+ throw EventFDException(msg);
}
}
diff --git a/common/utils/exception.hpp b/common/utils/exception.hpp
index 232b090..01bb380 100644
--- a/common/utils/exception.hpp
+++ b/common/utils/exception.hpp
@@ -39,6 +39,11 @@ struct UtilsException: public std::runtime_error {
explicit UtilsException(const std::string& error) : std::runtime_error(error) {}
};
+struct EventFDException: public UtilsException {
+
+ explicit EventFDException(const std::string& error) : UtilsException(error) {}
+};
+
struct ProvisionExistsException: public UtilsException {
explicit ProvisionExistsException(const std::string& error) : UtilsException(error) {}
diff --git a/libs/ipc/exception.hpp b/libs/ipc/exception.hpp
index 3fe7a5b..f757bcf 100644
--- a/libs/ipc/exception.hpp
+++ b/libs/ipc/exception.hpp
@@ -104,6 +104,25 @@ struct IPCTimeoutException: public IPCException {
};
/**
+ * Exception to indicate socket error
+ * @ingroup IPCException
+ */
+struct IPCSocketException: public IPCException {
+ IPCSocketException(const int code, const std::string& message)
+ : IPCException(message),
+ mCode(code)
+ {}
+
+ int getCode() const
+ {
+ return mCode;
+ }
+
+private:
+ int mCode;
+};
+
+/**
* Exception to indicate user error
* @ingroup IPCException
*/
diff --git a/libs/ipc/internals/processor.cpp b/libs/ipc/internals/processor.cpp
index 164d735..8cfeed1 100644
--- a/libs/ipc/internals/processor.cpp
+++ b/libs/ipc/internals/processor.cpp
@@ -130,7 +130,7 @@ void Processor::stop(bool wait)
mRequestQueue.pushBack(Event::FINISH, request);
}
- if(wait){
+ if (wait) {
LOGD(mLogPrefix + "Waiting for the Processor to stop");
// Wait till the FINISH request is served
diff --git a/libs/ipc/internals/socket.cpp b/libs/ipc/internals/socket.cpp
index a88ff0d..9bdfd35 100644
--- a/libs/ipc/internals/socket.cpp
+++ b/libs/ipc/internals/socket.cpp
@@ -150,7 +150,7 @@ int Socket::createSocketInternal(const std::string& path)
if (sockfd == -1) {
const std::string msg = "Error in socket: " + getSystemErrorMessage();
LOGE(msg);
- throw IPCException(msg);
+ throw IPCSocketException(errno, msg);
}
setFdOptions(sockfd);
@@ -210,7 +210,7 @@ Socket Socket::connectSocket(const std::string& path)
if (fd == -1) {
const std::string msg = "Error in socket: " + getSystemErrorMessage();
LOGE(msg);
- throw IPCException(msg);
+ throw IPCSocketException(errno, msg);
}
setFdOptions(fd);
diff --git a/libs/ipc/unique-id.cpp b/libs/ipc/unique-id.cpp
index bcdd4bc..4a121ec 100644
--- a/libs/ipc/unique-id.cpp
+++ b/libs/ipc/unique-id.cpp
@@ -55,9 +55,7 @@ UniqueID::operator std::string() const
std::ostream& operator<<(std::ostream& str, const UniqueID& id)
{
- char uuid[37];
- ::uuid_unparse(id.mUUID, uuid);
- str << id.mTime.tv_sec << "." << id.mTime.tv_nsec << ":" << uuid;
+ str << static_cast(id);
return str;
}
diff --git a/tests/scripts/vsm_launch_test.py b/tests/scripts/vsm_launch_test.py
index dd5831f..b4fe529 100755
--- a/tests/scripts/vsm_launch_test.py
+++ b/tests/scripts/vsm_launch_test.py
@@ -39,20 +39,15 @@ def launchTest(cmd=[], externalToolCmd=[], parsing=True):
if externalToolCmd and not _checkIfBinExists(externalToolCmd[0]):
return
- cmd[1:] = ["'{0}'".format(arg) if re.search("^\s*[^']*/.*<.*>\s*$", arg)
- else arg
- for arg in cmd[1:]]
-
log.info("Starting " + cmd[0] + " ...")
if parsing:
parser = Parser()
- command = " ".join(externalToolCmd + cmd + _defLaunchArgs)
- log.info("Invoking `" + command + "`")
- p = subprocess.Popen(command,
- shell=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
+ commandString = " ".join(externalToolCmd + cmd + _defLaunchArgs)
+ log.info("Invoking `" + commandString + "`")
+ p = subprocess.Popen(externalToolCmd + cmd + _defLaunchArgs,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
testResult = parser.parseOutputFromProcess(p)
if testResult != "":
domResult = minidom.parseString(testResult)
@@ -63,10 +58,9 @@ def launchTest(cmd=[], externalToolCmd=[], parsing=True):
else:
# Launching process without coloring does not require report in XML form
# Avoid providing --report_format=XML, redirect std* by default to system's std*
- command = " ".join(externalToolCmd + cmd + _defLaunchArgs[1:])
- log.info("Invoking `" + command + "`")
- p = subprocess.Popen(command,
- shell=True)
+ commandString = " ".join(externalToolCmd + cmd + _defLaunchArgs[1:])
+ log.info("Invoking `" + commandString + "`")
+ p = subprocess.Popen(externalToolCmd + cmd + _defLaunchArgs[1:])
p.wait()
log.info(cmd[0] + " finished.")
@@ -82,7 +76,8 @@ def main():
group.add_argument('--valgrind', action='store_true',
help='Launch test binary inside Valgrind (assuming it is installed).')
group.add_argument('--gdb', action='store_true',
- help='Launch test binary with GDB (assuming it is installed).')
+ help='Launch test binary with a tool specified by $VSM_DEBUGGER variable. '
+ +'Defaults to gdb.')
argparser.add_argument('binary', nargs=argparse.REMAINDER,
help='Binary to be launched using script.')
@@ -90,7 +85,12 @@ def main():
if args[0].binary:
if args[0].gdb:
- launchTest(args[0].binary, externalToolCmd=_gdbCmd + args[1], parsing=False)
+ debuggerVar = os.getenv("VSM_DEBUGGER")
+ if (debuggerVar):
+ _customDebuggerCmd = debuggerVar.split()
+ else:
+ _customDebuggerCmd = _gdbCmd
+ launchTest(args[0].binary, externalToolCmd=_customDebuggerCmd + args[1], parsing=False)
elif args[0].valgrind:
launchTest(args[0].binary, externalToolCmd=_valgrindCmd + args[1])
else:
diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp
index 5ba540e..0e16806 100644
--- a/tests/unit_tests/ipc/ut-ipc.cpp
+++ b/tests/unit_tests/ipc/ut-ipc.cpp
@@ -37,6 +37,7 @@
#include "ipc/result.hpp"
#include "ipc/epoll/thread-dispatcher.hpp"
#include "ipc/epoll/glib-dispatcher.hpp"
+#include "utils/channel.hpp"
#include "utils/glib-loop.hpp"
#include "utils/latch.hpp"
#include "utils/value-latch.hpp"
@@ -53,8 +54,10 @@
#include
#include
#include
+#include
#include
#include
+#include
#include
@@ -207,7 +210,7 @@ void shortEchoCallback(const PeerID,
methodResult->set(returnData);
}
-PeerID connect(Service& s, Client& c)
+PeerID connectPeer(Service& s, Client& c)
{
// Connects the Client to the Service and returns Clients PeerID
ValueLatch peerIDLatch;
@@ -265,7 +268,7 @@ MULTI_FIXTURE_TEST_CASE(ServiceAddRemoveMethod, F, ThreadedFixture, GlibFixture)
s.setMethodHandler(2, returnDataCallback);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
testEcho(c, 1);
s.removeMethod(1);
@@ -281,7 +284,7 @@ MULTI_FIXTURE_TEST_CASE(ClientAddRemoveMethod, F, ThreadedFixture, GlibFixture)
c.setMethodHandler(1, returnEmptyCallback);
c.setMethodHandler(1, returnDataCallback);
- PeerID peerID = connect(s, c);
+ PeerID peerID = connectPeer(s, c);
c.setMethodHandler(1, echoCallback);
c.setMethodHandler(2, returnDataCallback);
@@ -294,6 +297,29 @@ MULTI_FIXTURE_TEST_CASE(ClientAddRemoveMethod, F, ThreadedFixture, GlibFixture)
BOOST_CHECK_THROW(testEcho(s, 1, peerID), IPCException);
}
+MULTI_FIXTURE_TEST_CASE(MethodResultGetPeerID, F, ThreadedFixture, GlibFixture)
+{
+ Service s(F::getPoll(), SOCKET_PATH);
+ Client c(F::getPoll(), SOCKET_PATH);
+
+ PeerID peerID = connectPeer(s, c);
+
+ s.setMethodHandler(
+ 1,
+ [&peerID](const PeerID,
+ std::shared_ptr&,
+ MethodResult::Pointer methodResult) {
+ methodResult->setVoid();
+ BOOST_CHECK_EQUAL(peerID, methodResult->getPeerID());
+ }
+ );
+
+ std::shared_ptr sentData(new SendData(32));
+ std::shared_ptr recvData = c.callSync(1,
+ sentData,
+ TIMEOUT);
+}
+
MULTI_FIXTURE_TEST_CASE(ServiceStartStop, F, ThreadedFixture, GlibFixture)
{
Service s(F::getPoll(), SOCKET_PATH);
@@ -334,7 +360,7 @@ MULTI_FIXTURE_TEST_CASE(SyncClientToServiceEcho, F, ThreadedFixture, GlibFixture
s.setMethodHandler(2, echoCallback);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
testEcho(c, 1);
testEcho(c, 2);
@@ -375,7 +401,7 @@ MULTI_FIXTURE_TEST_CASE(SyncServiceToClientEcho, F, ThreadedFixture, GlibFixture
Service s(F::getPoll(), SOCKET_PATH);
Client c(F::getPoll(), SOCKET_PATH);
c.setMethodHandler(1, echoCallback);
- PeerID peerID = connect(s, c);
+ PeerID peerID = connectPeer(s, c);
std::shared_ptr sentData(new SendData(56));
std::shared_ptr recvData = s.callSync(1, peerID, sentData);
@@ -414,7 +440,7 @@ MULTI_FIXTURE_TEST_CASE(AsyncServiceToClientEcho, F, ThreadedFixture, GlibFixtur
Service s(F::getPoll(), SOCKET_PATH);
Client c(F::getPoll(), SOCKET_PATH);
c.setMethodHandler(1, echoCallback);
- PeerID peerID = connect(s, c);
+ PeerID peerID = connectPeer(s, c);
// Async call
auto dataBack = [&recvDataLatch](Result && r) {
@@ -435,7 +461,7 @@ MULTI_FIXTURE_TEST_CASE(SyncTimeout, F, ThreadedFixture, GlibFixture)
s.setMethodHandler(1, longEchoCallback);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
std::shared_ptr sentData(new SendData(78));
BOOST_REQUIRE_THROW((c.callSync(1, sentData, TIMEOUT)), IPCException);
@@ -447,7 +473,7 @@ MULTI_FIXTURE_TEST_CASE(SerializationError, F, ThreadedFixture, GlibFixture)
s.setMethodHandler(1, echoCallback);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
std::shared_ptr throwingData(new ThrowOnAcceptData());
@@ -513,7 +539,7 @@ MULTI_FIXTURE_TEST_CASE(ReadTimeout, F, ThreadedFixture, GlibFixture)
s.setMethodHandler(1, longEchoCallback);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
// Test timeout on read
std::shared_ptr sentData(new SendData(334));
@@ -549,7 +575,7 @@ MULTI_FIXTURE_TEST_CASE(AddSignalInRuntime, F, ThreadedFixture, GlibFixture)
Service s(F::getPoll(), SOCKET_PATH);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
auto handlerA = [&recvDataLatchA](const PeerID, std::shared_ptr& data) {
recvDataLatchA.set(data);
@@ -597,7 +623,7 @@ MULTI_FIXTURE_TEST_CASE(AddSignalOffline, F, ThreadedFixture, GlibFixture)
c.setSignalHandler(1, handlerA);
c.setSignalHandler(2, handlerB);
- connect(s, c);
+ connectPeer(s, c);
// Wait for the information about the signals to propagate
std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT));
@@ -621,7 +647,7 @@ MULTI_FIXTURE_TEST_CASE(UsersError, F, ThreadedFixture, GlibFixture)
Service s(F::getPoll(), SOCKET_PATH);
Client c(F::getPoll(), SOCKET_PATH);
- auto clientID = connect(s, c);
+ auto clientID = connectPeer(s, c);
auto throwingMethodHandler = [&](const PeerID, std::shared_ptr&, MethodResult::Pointer) {
throw IPCUserException(TEST_ERROR_CODE, TEST_ERROR_MESSAGE);
@@ -655,7 +681,7 @@ MULTI_FIXTURE_TEST_CASE(AsyncResult, F, ThreadedFixture, GlibFixture)
Service s(F::getPoll(), SOCKET_PATH);
Client c(F::getPoll(), SOCKET_PATH);
- auto clientID = connect(s, c);
+ auto clientID = connectPeer(s, c);
auto errorMethodHandler = [&](const PeerID, std::shared_ptr&, MethodResult::Pointer methodResult) {
std::async(std::launch::async, [&, methodResult] {
@@ -718,7 +744,7 @@ MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture)
Client c(F::getPoll(), SOCKET_PATH);
s.setSignalHandler(2, signalHandler);
- connect(s, c);
+ connectPeer(s, c);
testEcho(c, 1);
@@ -749,7 +775,7 @@ MULTI_FIXTURE_TEST_CASE(FDSendReceive, F, ThreadedFixture, GlibFixture)
s.setMethodHandler(1, methodHandler);
Client c(F::getPoll(), SOCKET_PATH);
- connect(s, c);
+ connectPeer(s, c);
std::shared_ptr fdData;
std::shared_ptr sentData(new EmptyData());
@@ -762,36 +788,69 @@ MULTI_FIXTURE_TEST_CASE(FDSendReceive, F, ThreadedFixture, GlibFixture)
::close(fdData->fd.value);
}
-// MULTI_FIXTURE_TEST_CASE(ConnectionLimit, F, ThreadedFixture, GlibFixture)
-// {
-// unsigned oldLimit = ipc::getMaxFDNumber();
-// ipc::setMaxFDNumber(50);
-
-// // Setup Service and many Clients
-// Service s(F::getPoll(), SOCKET_PATH);
-// s.setMethodHandler(1, echoCallback);
-// s.start();
-
-// std::list clients;
-// for (int i = 0; i < 100; ++i) {
-// try {
-// clients.push_back(Client(F::getPoll(), SOCKET_PATH));
-// clients.back().start();
-// } catch (...) {}
-// }
-
-// unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
-// std::mt19937 generator(seed);
-// for (auto it = clients.begin(); it != clients.end(); ++it) {
-// try {
-// std::shared_ptr sentData(new SendData(generator()));
-// std::shared_ptr recvData = it->callSync(1, sentData);
-// BOOST_CHECK_EQUAL(recvData->intVal, sentData->intVal);
-// } catch (...) {}
-// }
-
-// ipc::setMaxFDNumber(oldLimit);
-// }
+BOOST_AUTO_TEST_CASE(ConnectionLimit)
+{
+ const unsigned oldLimit = utils::getMaxFDNumber();
+ const unsigned newLimit = 32;
+ ScopedDir scopedDir(TEST_DIR);
+
+ Channel c;
+
+ const pid_t chpid = ::fork();
+ BOOST_CHECK_NE(chpid, -1);
+
+ if (chpid) {
+ // Setup Service
+ ThreadDispatcher td;
+ Service s(td.getPoll(), SOCKET_PATH);
+ s.setMethodHandler(1, echoCallback);
+ s.start();
+
+ c.setLeft();
+ try {
+ // inform the Client
+ c.write(true);
+ } catch (...) {
+ kill(chpid, 9);
+ throw;
+ }
+
+ int status;
+ BOOST_CHECK_EQUAL(::waitpid(chpid, &status, 0), chpid);
+ BOOST_CHECK_EQUAL(status, EXIT_SUCCESS);
+ } else {
+ int ret = EXIT_FAILURE;
+ utils::setMaxFDNumber(newLimit);
+
+ c.setRight();
+ try {
+ // wait for the Service
+ c.read();
+ } catch(...) {
+ ::_exit(EXIT_FAILURE);
+ }
+
+ // Setup Clients
+ ThreadDispatcher td;
+ std::list clients;
+ try {
+ for (unsigned i = 0; i < 2 * newLimit; ++i) {
+ clients.emplace_back(td.getPoll(), SOCKET_PATH);
+ clients.back().start();
+ }
+ } catch (const EventFDException& e) {
+ ret = EXIT_SUCCESS;
+ } catch (const IPCSocketException& e) {
+ if (e.getCode() == EMFILE) {
+ ret = EXIT_SUCCESS;
+ }
+ }
+
+ utils::setMaxFDNumber(oldLimit);
+
+ ::_exit(ret);
+ }
+}
diff --git a/tests/unit_tests/ipc/ut-unique-id.cpp b/tests/unit_tests/ipc/ut-unique-id.cpp
index 05ce1bb..e60bc88 100644
--- a/tests/unit_tests/ipc/ut-unique-id.cpp
+++ b/tests/unit_tests/ipc/ut-unique-id.cpp
@@ -29,6 +29,7 @@
#include "ipc/unique-id.hpp"
#include
+#include
#include
namespace {
@@ -70,4 +71,22 @@ BOOST_AUTO_TEST_CASE(DoubleGenerate)
BOOST_CHECK_NE(uid1, uid2);
}
+// compare two empty UIDs
+BOOST_AUTO_TEST_CASE(EmptyCompare)
+{
+ ipc::UniqueID uid1, uid2;
+
+ BOOST_CHECK_EQUAL(uid1, uid2);
+}
+
+// pass empty UID to a stream
+BOOST_AUTO_TEST_CASE(StreamOperator)
+{
+ ipc::UniqueID uid;
+ std::stringstream ss;
+
+ ss << uid;
+ BOOST_CHECK_EQUAL(ss.str(), "0.0:" + EMPTY_UUID);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/unit_tests/utils/ut-fd-utils.cpp b/tests/unit_tests/utils/ut-fd-utils.cpp
new file mode 100644
index 0000000..3c0962d
--- /dev/null
+++ b/tests/unit_tests/utils/ut-fd-utils.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Pawel Kubik (p.kubik@samsung.com)
+ *
+ * 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
+ */
+
+
+/**
+ * @file
+ * @author Pawel Kubik (p.kubik@samsung.com)
+ * @brief Unit tests of fd utils
+ */
+
+#include "config.hpp"
+#include "ut.hpp"
+
+#include "utils/fd-utils.hpp"
+
+#include "logger/logger.hpp"
+
+
+using namespace utils;
+
+
+BOOST_AUTO_TEST_SUITE(FDUtilsSuite)
+
+BOOST_AUTO_TEST_CASE(GetSetMaxFDNumber)
+{
+ unsigned oldLimit = utils::getMaxFDNumber();
+ unsigned newLimit = 50;
+
+ utils::setMaxFDNumber(newLimit);
+ BOOST_CHECK_EQUAL(newLimit, utils::getMaxFDNumber());
+
+ utils::setMaxFDNumber(oldLimit);
+ BOOST_CHECK_EQUAL(oldLimit, utils::getMaxFDNumber());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
--
2.7.4
From 95bde33bc81d699e404fc1d3ffe378ec98b5f259 Mon Sep 17 00:00:00 2001
From: Lukasz Pawelczyk
Date: Fri, 9 Oct 2015 16:37:59 +0200
Subject: [PATCH 03/16] Fix the color codes effectively fixing the BOLD colors
[Feature] N/A
[Cause] All the colors were always bold
[Solution] Use proper ANSII color codes
[Verification] Visual
Change-Id: Id8be7fbbdad46e9952fcecfa2bdd8328eb4e7164
---
common/utils/ccolor.hpp | 16 ++++++++--------
tests/scripts/vsm_test_parser.py | 16 ++++++++--------
2 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/common/utils/ccolor.hpp b/common/utils/ccolor.hpp
index 1700967..b579354 100644
--- a/common/utils/ccolor.hpp
+++ b/common/utils/ccolor.hpp
@@ -31,14 +31,14 @@ namespace utils {
enum class Color : unsigned int {
DEFAULT = 0,
- BLACK = 90,
- RED = 91,
- GREEN = 92,
- YELLOW = 93,
- BLUE = 94,
- MAGENTA = 95,
- CYAN = 96,
- WHITE = 97
+ BLACK = 30,
+ RED = 31,
+ GREEN = 32,
+ YELLOW = 33,
+ BLUE = 34,
+ MAGENTA = 35,
+ CYAN = 36,
+ WHITE = 37
};
enum class Attributes : unsigned int {
diff --git a/tests/scripts/vsm_test_parser.py b/tests/scripts/vsm_test_parser.py
index fc0eae6..ee63a55 100644
--- a/tests/scripts/vsm_test_parser.py
+++ b/tests/scripts/vsm_test_parser.py
@@ -3,14 +3,14 @@ import sys
-BLACK = "\033[90m"
-RED = "\033[91m"
-GREEN = "\033[92m"
-YELLOW = "\033[93m"
-BLUE = "\033[94m"
-MAGENTA = "\033[95m"
-CYAN = "\033[96m"
-WHITE = "\033[97m"
+BLACK = "\033[30m"
+RED = "\033[31m"
+GREEN = "\033[32m"
+YELLOW = "\033[33m"
+BLUE = "\033[34m"
+MAGENTA = "\033[35m"
+CYAN = "\033[36m"
+WHITE = "\033[37m"
BOLD = "\033[1m"
ENDC = "\033[0m"
--
2.7.4
From 2f62c1f25d9a9a8360f3d671ade64b61dd857f97 Mon Sep 17 00:00:00 2001
From: Krzysztof Dynowski
Date: Thu, 8 Oct 2015 14:03:43 +0200
Subject: [PATCH 04/16] lxcpp: cgroups API
[Feature] Control-groups API for containers
[Cause] N/A
[Solution] N/A
[Verification] N/A
Change-Id: I69605383b40e3b3e1a8c2f6942e85023b367728e
---
libs/lxcpp/CMakeLists.txt | 3 +-
libs/lxcpp/cgroups/cgroup.cpp | 26 +++++++++++++
libs/lxcpp/cgroups/cgroup.hpp | 83 ++++++++++++++++++++++++++++++++++++++++
libs/lxcpp/cgroups/subsystem.hpp | 81 +++++++++++++++++++++++++++++++++++++++
4 files changed, 192 insertions(+), 1 deletion(-)
create mode 100644 libs/lxcpp/cgroups/cgroup.cpp
create mode 100644 libs/lxcpp/cgroups/cgroup.hpp
create mode 100644 libs/lxcpp/cgroups/subsystem.hpp
diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt
index 9e49843..0d35bad 100644
--- a/libs/lxcpp/CMakeLists.txt
+++ b/libs/lxcpp/CMakeLists.txt
@@ -33,13 +33,14 @@ FILE(GLOB HEADERS_COMMANDS commands/*.hpp)
FILE(GLOB SRCS *.cpp *.hpp)
FILE(GLOB SRCS_COMMANDS commands/*.cpp)
+FILE(GLOB SRCS_CGROUPS cgroups/*.cpp)
SET(_LIB_VERSION_ "${VERSION}")
SET(_LIB_SOVERSION_ "0")
SET(PC_FILE "lib${PROJECT_NAME}.pc")
## Setup target ################################################################
-ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_COMMANDS})
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_COMMANDS} ${SRCS_CGROUPS})
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
diff --git a/libs/lxcpp/cgroups/cgroup.cpp b/libs/lxcpp/cgroups/cgroup.cpp
new file mode 100644
index 0000000..574af61
--- /dev/null
+++ b/libs/lxcpp/cgroups/cgroup.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Control-groups management
+ */
+
+#include "lxcpp/cgroups/cgroup.hpp"
+
+// added this file now, to make hpp go through compilation
diff --git a/libs/lxcpp/cgroups/cgroup.hpp b/libs/lxcpp/cgroups/cgroup.hpp
new file mode 100644
index 0000000..b47268f
--- /dev/null
+++ b/libs/lxcpp/cgroups/cgroup.hpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Control-groups management
+ */
+
+#ifndef LXCPP_CGROUPS_CGROUP_HPP
+#define LXCPP_CGROUPS_CGROUP_HPP
+
+#include "lxcpp/cgroups/subsystem.hpp"
+
+class CGroup {
+
+public:
+ /**
+ * Define control-group object
+ */
+ CGroup(const Subsystem& subsys, const std::string& name) :
+ mSubsys(subsys),
+ mName(name)
+ {
+ }
+
+ /**
+ * Check if cgroup exists
+ * @return true if cgroup path (subsys.path / mName) exists
+ */
+ bool exists();
+
+ /**
+ * Create cgroup directory
+ * Equivalent of: mkdir subsys.path / mName
+ */
+ void create();
+
+ /**
+ * Destroy cgroup directory
+ * Equivalent of: rmdir subsys.path / mName
+ * Note: set memory.force_empty before removing a cgroup to avoid moving out-of-use page caches to parent
+ */
+ void destroy();
+
+ /**
+ * Set cgroup parameter to value (name validity depends on subsystem)
+ * Equivalent of: echo value > mSubsys_path/mName/mSubsys_name.param
+ */
+ void setValue(const std::string& param, const std::string& value);
+
+ /**
+ * Get cgroup parameter
+ * Equivalent of: cat mSubsys_path/mName/mSubsys_name.param
+ */
+ std::string getValue(const std::string& key);
+
+ /**
+ * Move process to this cgroup (process can't be removed from a cgroup)
+ * Equivalent of: echo pid > mSubsys_path/mName/tasks
+ */
+ void moveProcess(pid_t pid);
+
+private:
+ const Subsystem& mSubsys; // referred subsystem
+ const std::string& mName; // path relative to subsystem "root"
+};
+
+#endif // LXCPP_CGROUPS_CGROUP_HPP
diff --git a/libs/lxcpp/cgroups/subsystem.hpp b/libs/lxcpp/cgroups/subsystem.hpp
new file mode 100644
index 0000000..bb9887e
--- /dev/null
+++ b/libs/lxcpp/cgroups/subsystem.hpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Krzysztof Dynowski (k.dynowski@samsumg.com)
+ * @brief Control-groups management
+ */
+
+#ifndef LXCPP_CGROUPS_SUBSYSTEM_HPP
+#define LXCPP_CGROUPS_SUBSYSTEM_HPP
+
+#include
+
+#include
+#include
+
+class Subsystem {
+public:
+ /**
+ * Define subsystem object
+ */
+ Subsystem(const std::string& name);
+
+ /**
+ * Check if named subsystem is supported by the kernel
+ * @return true if subsystem is listed in /proc/cgroups
+ */
+ bool isAvailable();
+
+ /**
+ * Check if named subsystem is mounted (added to hierarchy)
+ * @return true if subsystem has a mount point (as read from /proc/mounts)
+ */
+ bool isAttached();
+
+ /**
+ * Attach subsystem hierarchy to filesystem
+ * Equivalent of: mount -t cgroup -o subs(coma-sep) subs(underln-sep) path
+ */
+ static void attach(const std::string& path, std::vector subs);
+
+ /**
+ * Detach subsstem hierarchy from filesystem
+ * Equivalent of: umount path
+ */
+ static void detach(const std::string& path);
+
+ /**
+ * Get list of available subsytems
+ * @return parse contents of /proc/cgroups
+ */
+ static std::vector availableSubsystems();
+
+ /**
+ * Get control groups list for a process (in format subsys_name:cgroup_name)
+ * eg. "cpu:/user/test_user"
+ * Equivalent of: cat /proc/pid/cgroup
+ */
+ static std::vector getCGroups(pid_t pid);
+
+private:
+ const std::string& mName;
+ std::string mPath;
+};
+
+#endif // LXCPP_CGROUPS_SUBSYSTEM_HPP
--
2.7.4
From 64b5dbb4b7ae47002e35e05765637c04c526b0b6 Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Wed, 7 Oct 2015 18:13:52 +0200
Subject: [PATCH 05/16] config: enum class serialization
[Feature] Serialization of strongly typed enums
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests.
Change-Id: Ie4d112995cff8d58c0cc6fad6c0646ec03d5aa83
---
libs/config/from-fdstore-visitor.hpp | 6 ++++++
libs/config/from-gvariant-visitor.hpp | 7 +++++++
libs/config/from-json-visitor.hpp | 9 ++++++++-
libs/config/from-kvjson-visitor.hpp | 11 ++++++++++-
libs/config/kvstore.hpp | 26 ++++++++++++++++++++++----
libs/config/to-fdstore-visitor.hpp | 6 ++++++
libs/config/to-gvariant-visitor.hpp | 6 ++++++
libs/config/to-json-visitor.hpp | 9 ++++++++-
tests/unit_tests/config/testconfig-example.hpp | 9 +++++++++
tests/unit_tests/config/ut-configuration.cpp | 1 +
10 files changed, 83 insertions(+), 7 deletions(-)
diff --git a/libs/config/from-fdstore-visitor.hpp b/libs/config/from-fdstore-visitor.hpp
index f0c8dbe..8b7d082 100644
--- a/libs/config/from-fdstore-visitor.hpp
+++ b/libs/config/from-fdstore-visitor.hpp
@@ -93,6 +93,12 @@ private:
value.accept(visitor);
}
+ template::value, int>::type = 0>
+ void readInternal(T& value)
+ {
+ readInternal(*reinterpret_cast::type*>(&value));
+ }
+
template
void readInternal(std::vector& values)
{
diff --git a/libs/config/from-gvariant-visitor.hpp b/libs/config/from-gvariant-visitor.hpp
index afc1beb..78e001d 100644
--- a/libs/config/from-gvariant-visitor.hpp
+++ b/libs/config/from-gvariant-visitor.hpp
@@ -200,6 +200,13 @@ private:
visitFields(values, &visitor, &iter);
}
+ template::value, int>::type = 0>
+ static void fromGVariant(GVariant* object, T& value)
+ {
+ fromGVariant(object,
+ *reinterpret_cast::type*>(&value));
+ }
+
template
static typename std::enable_if::value>::type
fromGVariant(GVariant* object, T& value)
diff --git a/libs/config/from-json-visitor.hpp b/libs/config/from-json-visitor.hpp
index 9bdf19b..b599084 100644
--- a/libs/config/from-json-visitor.hpp
+++ b/libs/config/from-json-visitor.hpp
@@ -192,7 +192,14 @@ private:
visitFields(values, &visitor, object, idx);
}
- template::value>::type>
+ template::value, int>::type = 0>
+ static void fromJsonObject(json_object* object, T& value)
+ {
+ fromJsonObject(object,
+ *reinterpret_cast::type*>(&value));
+ }
+
+ template::value, int>::type = 0>
static void fromJsonObject(json_object* object, T& value)
{
checkType(object, json_type_object);
diff --git a/libs/config/from-kvjson-visitor.hpp b/libs/config/from-kvjson-visitor.hpp
index d9dbce7..e66b90d 100644
--- a/libs/config/from-kvjson-visitor.hpp
+++ b/libs/config/from-kvjson-visitor.hpp
@@ -107,7 +107,16 @@ private:
mObject = object ? json_object_get(object) : nullptr;
}
- template::value, int>::type = 0>
+ template::value, int>::type = 0>
+ void getValue(const std::string& name, T& t)
+ {
+ getValue(name,
+ *reinterpret_cast::type*>(&t));
+ }
+
+ template::value &&
+ !std::is_enum::value, int>::type = 0>
void getValue(const std::string& name, T& t)
{
std::string k = key(mKeyPrefix, name);
diff --git a/libs/config/kvstore.hpp b/libs/config/kvstore.hpp
index 1206d08..40aa199 100644
--- a/libs/config/kvstore.hpp
+++ b/libs/config/kvstore.hpp
@@ -139,7 +139,9 @@ private:
void setInternal(const std::string& key, const char* value);
void setInternal(const std::string& key, const std::initializer_list& values);
void setInternal(const std::string& key, const std::vector& values);
- template
+ template::value, int>::type = 0>
+ void setInternal(const std::string& key, const T& value);
+ template::value, int>::type = 0>
void setInternal(const std::string& key, const T& value);
template
void setInternal(const std::string& key, const std::vector& values);
@@ -151,7 +153,9 @@ private:
std::string getInternal(const std::string& key, std::string*);
char* getInternal(const std::string& key, char**);
std::vector getInternal(const std::string& key, std::vector*);
- template
+ template::value, int>::type = 0>
+ T getInternal(const std::string& key, T*);
+ template::value, int>::type = 0>
T getInternal(const std::string& key, T*);
template
std::vector getInternal(const std::string& key, std::vector*);
@@ -195,12 +199,19 @@ T fromString(const std::string& strValue)
} // namespace
-template
+template::value, int>::type>
void KVStore::setInternal(const std::string& key, const T& value)
{
setInternal(key, toString(value));
}
+template::value, int>::type>
+void KVStore::setInternal(const std::string& key, const T& value)
+{
+ setInternal(key,
+ static_cast::type>(value));
+}
+
template
void KVStore::setInternal(const std::string& key, const std::vector& values)
{
@@ -247,12 +258,19 @@ void KVStore::setInternal(const std::string& key, const std::pair& values)
setInternal(key, strValues);
}
-template
+template::value, int>::type>
T KVStore::getInternal(const std::string& key, T*)
{
return fromString(getInternal(key, static_cast(nullptr)));
}
+template::value, int>::type>
+T KVStore::getInternal(const std::string& key, T*)
+{
+ return static_cast(getInternal(key,
+ static_cast::type*>(nullptr)));
+}
+
template
std::array KVStore::getInternal(const std::string& key, std::array*)
{
diff --git a/libs/config/to-fdstore-visitor.hpp b/libs/config/to-fdstore-visitor.hpp
index ba9bb8e..b3e6b84 100644
--- a/libs/config/to-fdstore-visitor.hpp
+++ b/libs/config/to-fdstore-visitor.hpp
@@ -78,6 +78,12 @@ private:
mStore.sendFD(fd.value);
}
+ template::value, int>::type = 0>
+ void writeInternal(const T& value)
+ {
+ writeInternal(static_cast::type>(value));
+ }
+
template::value, int>::type = 0>
void writeInternal(const T& value)
{
diff --git a/libs/config/to-gvariant-visitor.hpp b/libs/config/to-gvariant-visitor.hpp
index 09c04e6..c0df2da 100644
--- a/libs/config/to-gvariant-visitor.hpp
+++ b/libs/config/to-gvariant-visitor.hpp
@@ -143,6 +143,12 @@ private:
g_variant_builder_close(mBuilder);
}
+ template::value, int>::type = 0>
+ void writeInternal(const T& value)
+ {
+ writeInternal(static_cast::type>(value));
+ }
+
template
typename std::enable_if::value && !isUnion::value>::type
writeInternal(const T& value)
diff --git a/libs/config/to-json-visitor.hpp b/libs/config/to-json-visitor.hpp
index 3b8facf..ba0d6ed 100644
--- a/libs/config/to-json-visitor.hpp
+++ b/libs/config/to-json-visitor.hpp
@@ -168,13 +168,20 @@ private:
return array;
}
- template::value>::type>
+ template::value, int>::type = 0>
static json_object* toJsonObject(const T& value)
{
ToJsonVisitor visitor;
value.accept(visitor);
return visitor.detach();
}
+
+ template::value, int>::type = 0>
+ static json_object* toJsonObject(const T& value)
+ {
+ return toJsonObject(static_cast::type>(value));
+ }
+
};
} // namespace config
diff --git a/tests/unit_tests/config/testconfig-example.hpp b/tests/unit_tests/config/testconfig-example.hpp
index 3cdd876..0ddd975 100644
--- a/tests/unit_tests/config/testconfig-example.hpp
+++ b/tests/unit_tests/config/testconfig-example.hpp
@@ -29,6 +29,11 @@
#include "config/fields.hpp"
#include "config/fields-union.hpp"
+enum class TestEnum: int {
+ FIRST = 0,
+ SECOND = 12
+};
+
struct TestConfig {
// subtree class
struct SubConfig {
@@ -91,6 +96,7 @@ struct TestConfig {
char* cstringVal;
double doubleVal;
bool boolVal;
+ TestEnum enumVal;
std::vector emptyIntVector;
std::vector intVector;
@@ -118,6 +124,7 @@ struct TestConfig {
cstringVal,
doubleVal,
boolVal,
+ enumVal,
emptyIntVector,
intVector,
@@ -163,6 +170,7 @@ const std::string jsonTestString =
"\"cstringVal\": \"blah\", "
"\"doubleVal\": -1.234000, "
"\"boolVal\": true, "
+ "\"enumVal\": 12, "
"\"emptyIntVector\": [ ], "
"\"intVector\": [ 1, 2, 3 ], "
"\"stringVector\": [ \"a\", \"b\" ], "
@@ -188,6 +196,7 @@ const std::string jsonEmptyTestString =
"\"stringVal\": \"\", "
"\"cstringVal\": \"\", "
"\"boolVal\": false, "
+ "\"enumVal\": 0, "
"\"emptyIntVector\": [ ], "
"\"intVector\": [ ], "
"\"stringVector\": [ ], "
diff --git a/tests/unit_tests/config/ut-configuration.cpp b/tests/unit_tests/config/ut-configuration.cpp
index e50ed92..ab1a200 100644
--- a/tests/unit_tests/config/ut-configuration.cpp
+++ b/tests/unit_tests/config/ut-configuration.cpp
@@ -67,6 +67,7 @@ BOOST_AUTO_TEST_CASE(FromJsonString)
BOOST_CHECK_EQUAL("blah", testConfig.cstringVal);
BOOST_CHECK_CLOSE(-1.234, testConfig.doubleVal, TOLERANCE);
BOOST_CHECK_EQUAL(true, testConfig.boolVal);
+ BOOST_CHECK(TestEnum::SECOND == testConfig.enumVal);
BOOST_REQUIRE_EQUAL(0, testConfig.emptyIntVector.size());
--
2.7.4
From 9f5816c9a34f40b6acfc8924ee914d5165c1e35f Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Thu, 8 Oct 2015 14:19:22 +0200
Subject: [PATCH 06/16] lxcpp: Switch on serialization from libConfig
[Feature] Use std::pair and enum serialization
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests
Change-Id: I6edb4543bf85eacfb2efe13065970326b30aba17
---
libs/lxcpp/attach/attach-config.hpp | 14 ++++++--------
libs/lxcpp/attach/attach-helper.cpp | 4 ++--
libs/lxcpp/commands/attach.cpp | 2 +-
libs/lxcpp/commands/attach.hpp | 2 +-
libs/lxcpp/container-impl.cpp | 2 +-
libs/lxcpp/container-impl.hpp | 2 +-
libs/lxcpp/container.hpp | 2 +-
libs/lxcpp/guard/guard.cpp | 11 +----------
libs/lxcpp/process.cpp | 16 ++++++++++++++++
libs/lxcpp/process.hpp | 2 ++
10 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/libs/lxcpp/attach/attach-config.hpp b/libs/lxcpp/attach/attach-config.hpp
index 9788abe..94e2626 100644
--- a/libs/lxcpp/attach/attach-config.hpp
+++ b/libs/lxcpp/attach/attach-config.hpp
@@ -39,7 +39,7 @@ namespace lxcpp {
struct AttachConfig {
/// Arguments passed by user, argv[0] is the binary's path in container
- std::vector argv;
+ std::vector argv;
/// PID of the container's init process
pid_t initPid;
@@ -73,7 +73,7 @@ struct AttachConfig {
AttachConfig() = default;
- AttachConfig(const std::vector& argv,
+ AttachConfig(const std::vector& argv,
const pid_t initPid,
const std::vector& namespaces,
const uid_t uid,
@@ -99,19 +99,17 @@ struct AttachConfig {
CONFIG_REGISTER
(
//TODO: Uncomment and fix cstring serialization
- // argv,
+ argv,
initPid,
- //TODO: Uncomment and fix Namespace serialization (or remove Namespace)
- // namespaces,
+ namespaces,
uid,
gid,
ttyFD,
supplementaryGids,
capsToKeep,
workDirInContainer,
- envToKeep
- //TODO: Uncomment and fix std::pair serialization
- // envToSet
+ envToKeep,
+ envToSet
)
};
diff --git a/libs/lxcpp/attach/attach-helper.cpp b/libs/lxcpp/attach/attach-helper.cpp
index 321502f..5aaaecb 100644
--- a/libs/lxcpp/attach/attach-helper.cpp
+++ b/libs/lxcpp/attach/attach-helper.cpp
@@ -70,8 +70,8 @@ int child(void* data)
::_exit(EXIT_FAILURE);
}
- // Run user's binary
- ::execve(config.argv[0], const_cast(config.argv.data()), nullptr);
+ lxcpp::execve(config.argv);
+
return EXIT_FAILURE;
}
diff --git a/libs/lxcpp/commands/attach.cpp b/libs/lxcpp/commands/attach.cpp
index 2bfa592..a059986 100644
--- a/libs/lxcpp/commands/attach.cpp
+++ b/libs/lxcpp/commands/attach.cpp
@@ -34,7 +34,7 @@
namespace lxcpp {
Attach::Attach(const lxcpp::ContainerImpl& container,
- const std::vector& argv,
+ const std::vector& argv,
const uid_t uid,
const gid_t gid,
const std::string& ttyPath,
diff --git a/libs/lxcpp/commands/attach.hpp b/libs/lxcpp/commands/attach.hpp
index ce39b83..123a384 100644
--- a/libs/lxcpp/commands/attach.hpp
+++ b/libs/lxcpp/commands/attach.hpp
@@ -56,7 +56,7 @@ public:
* @param envToSet new environment variables that will be set
*/
Attach(const lxcpp::ContainerImpl& container,
- const std::vector& argv,
+ const std::vector& argv,
const uid_t uid,
const gid_t gid,
const std::string& ttyPath,
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index c7035e4..9ff4b52 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -205,7 +205,7 @@ void ContainerImpl::reboot()
throw NotImplementedException();
}
-void ContainerImpl::attach(const std::vector& argv,
+void ContainerImpl::attach(const std::vector& argv,
const std::string& cwdInContainer)
{
Attach attach(*this,
diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp
index 7393974..041303b 100644
--- a/libs/lxcpp/container-impl.hpp
+++ b/libs/lxcpp/container-impl.hpp
@@ -65,7 +65,7 @@ public:
void reboot();
// Other
- void attach(const std::vector& argv,
+ void attach(const std::vector& argv,
const std::string& cwdInContainer);
// Network interfaces setup/config
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index 51dda8c..7f98aed 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -71,7 +71,7 @@ public:
virtual void reboot() = 0;
// Other
- virtual void attach(const std::vector& argv,
+ virtual void attach(const std::vector& argv,
const std::string& cwdInContainer) = 0;
// Network interfaces setup/config
diff --git a/libs/lxcpp/guard/guard.cpp b/libs/lxcpp/guard/guard.cpp
index 952cdf5..369d423 100644
--- a/libs/lxcpp/guard/guard.cpp
+++ b/libs/lxcpp/guard/guard.cpp
@@ -38,16 +38,7 @@ namespace lxcpp {
void startContainer(const ContainerConfig &cfg)
{
- std::vector argv;
- argv.reserve(cfg.mInit.size() + 1);
- for (auto const & it : cfg.mInit) {
- argv.push_back(it.c_str());
- }
- argv.push_back(nullptr);
-
- LOGD("Executing container's init: " << argv[0]);
- ::execve(argv[0], const_cast(argv.data()), NULL);
- ::_exit(EXIT_FAILURE);
+ lxcpp::execve(cfg.mInit);
}
int startGuard(int channelFD)
diff --git a/libs/lxcpp/process.cpp b/libs/lxcpp/process.cpp
index 0353d82..204dec2 100644
--- a/libs/lxcpp/process.cpp
+++ b/libs/lxcpp/process.cpp
@@ -156,4 +156,20 @@ void unshare(const Namespace ns)
throw ProcessSetupException(msg);
}
}
+
+void execve(const std::vector& argv)
+{
+ // Prepare the arguments
+ std::vector tmpArgv;
+ tmpArgv.reserve(argv.size() + 1);
+
+ for (auto const &str : argv) {
+ tmpArgv.push_back(str.c_str());
+ }
+ tmpArgv.push_back(nullptr);
+
+ // Run user's binary
+ ::execve(tmpArgv[0], const_cast(tmpArgv.data()), nullptr);
+}
+
} // namespace lxcpp
diff --git a/libs/lxcpp/process.hpp b/libs/lxcpp/process.hpp
index 869e3d6..75c1e4f 100644
--- a/libs/lxcpp/process.hpp
+++ b/libs/lxcpp/process.hpp
@@ -49,6 +49,8 @@ int waitpid(const pid_t pid);
void unshare(const Namespace ns);
+void execve(const std::vector& argv);
+
} // namespace lxcpp
#endif // LXCPP_PROCESS_HPP
\ No newline at end of file
--
2.7.4
From 3b6129779f3829bd1a1987087ccdd7d14a4af98d Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Thu, 8 Oct 2015 17:26:23 +0200
Subject: [PATCH 07/16] lxcpp: Added simple container tests
[Feature] setInit and setLogger tests
[Cause] N/A
[Solution] N/A
[Verification] Build, install, run tests
Change-Id: I944c76aa4483c6c287a6b032b4d7456ab58f7d44
---
libs/lxcpp/container.hpp | 2 +-
libs/lxcpp/guard/guard.cpp | 2 +-
tests/unit_tests/lxcpp/ut-container.cpp | 75 ++++++++++++++++++++++++++++++++-
3 files changed, 75 insertions(+), 4 deletions(-)
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index 7f98aed..e3d537f 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -59,7 +59,7 @@ public:
virtual void setLogger(const logger::LogType type,
const logger::LogLevel level,
- const std::string &arg) = 0;
+ const std::string &arg = "") = 0;
virtual void setTerminalCount(const unsigned int count) = 0;
diff --git a/libs/lxcpp/guard/guard.cpp b/libs/lxcpp/guard/guard.cpp
index 369d423..28e572a 100644
--- a/libs/lxcpp/guard/guard.cpp
+++ b/libs/lxcpp/guard/guard.cpp
@@ -60,7 +60,7 @@ int startGuard(int channelFD)
setProcTitle(title);
} catch (std::exception &e) {
// Ignore, this is optional
- LOGW("Failed to set the guard process title");
+ LOGW("Failed to set the guard process title: " << e.what());
}
// TODO: container preparation part 1
diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp
index 35672e0..ff72b94 100644
--- a/tests/unit_tests/lxcpp/ut-container.cpp
+++ b/tests/unit_tests/lxcpp/ut-container.cpp
@@ -29,10 +29,29 @@
#include "lxcpp/lxcpp.hpp"
#include "lxcpp/exception.hpp"
+#include "utils/scoped-dir.hpp"
+
+#include
+
namespace {
+const std::string TEST_DIR = "/tmp/ut-zones";
+const std::string ROOT_DIR = TEST_DIR + "/root";
+const std::string NON_EXISTANT_BINARY = TEST_DIR + "/nonexistantpath/bash";
+const std::string LOGGER_FILE = TEST_DIR + "/loggerFile";
+
+const std::vector COMMAND = {"/bin/bash",
+ "-c", "trap exit SIGTERM; while true; do sleep 0.1; done"
+ };
+
struct Fixture {
- Fixture() {}
+ utils::ScopedDir mTestDir;
+ utils::ScopedDir mRoot;
+
+ Fixture()
+ :mTestDir(TEST_DIR),
+ mRoot(ROOT_DIR)
+ {}
~Fixture() {}
};
@@ -44,8 +63,60 @@ using namespace lxcpp;
BOOST_AUTO_TEST_CASE(ConstructorDestructor)
{
- auto c = createContainer("FirstTestContainer", "/");
+ auto c = createContainer("ConstructorDestructor", ROOT_DIR);
delete c;
}
+BOOST_AUTO_TEST_CASE(SetInit)
+{
+ auto c = std::unique_ptr(createContainer("SetInit", "/"));
+
+ BOOST_CHECK_THROW(c->setInit({""}), ConfigureException);
+ BOOST_CHECK_THROW(c->setInit({}), ConfigureException);
+ BOOST_CHECK_THROW(c->setInit({NON_EXISTANT_BINARY}), ConfigureException);
+
+ BOOST_CHECK_NO_THROW(c->setInit(COMMAND));
+}
+
+BOOST_AUTO_TEST_CASE(SetLogger)
+{
+ auto c = std::unique_ptr(createContainer("SetLogger", ROOT_DIR));
+
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_NULL,
+ logger::LogLevel::DEBUG));
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_JOURNALD,
+ logger::LogLevel::DEBUG));
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_SYSLOG,
+ logger::LogLevel::DEBUG));
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_STDERR,
+ logger::LogLevel::DEBUG));
+
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_FILE,
+ logger::LogLevel::DEBUG,
+ LOGGER_FILE));
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
+ logger::LogLevel::DEBUG,
+ LOGGER_FILE));
+
+ BOOST_CHECK_THROW(c->setLogger(logger::LogType::LOG_FILE,
+ logger::LogLevel::DEBUG,
+ ""),
+ BadArgument);
+
+ BOOST_CHECK_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
+ logger::LogLevel::DEBUG,
+ ""),
+ BadArgument);
+}
+
+// BOOST_AUTO_TEST_CASE(StartStop)
+// {
+// auto c = std::unique_ptr(createContainer("StartStop", "/"));
+// BOOST_CHECK_NO_THROW(c->setInit(COMMAND));
+// BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
+// logger::LogLevel::DEBUG,
+// LOGGER_FILE));
+// BOOST_CHECK_NO_THROW(c->start());
+// }
+
BOOST_AUTO_TEST_SUITE_END()
--
2.7.4
From 94f4fbe894f1b987af9cb4183f14f8c5c43010be Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Mon, 12 Oct 2015 12:43:10 +0200
Subject: [PATCH 08/16] lxcpp: Stopping container's init process
[Feature] Terminating container's init process
[Cause] N/A
[Solution] N/A
[Verification] Build, install and run tests
Change-Id: I77af77016d06555b6eea3e133e25a44574580c67
---
common/utils/signal.cpp | 11 +++++++
common/utils/signal.hpp | 1 +
libs/lxcpp/commands/stop.cpp | 51 ++++++++++++++++++++++++++++++
libs/lxcpp/commands/stop.hpp | 56 +++++++++++++++++++++++++++++++++
libs/lxcpp/container-impl.cpp | 4 ++-
libs/lxcpp/utils.cpp | 4 +--
tests/unit_tests/lxcpp/ut-container.cpp | 19 +++++------
7 files changed, 134 insertions(+), 12 deletions(-)
create mode 100644 libs/lxcpp/commands/stop.cpp
create mode 100644 libs/lxcpp/commands/stop.hpp
diff --git a/common/utils/signal.cpp b/common/utils/signal.cpp
index bad3b0b..51c45b1 100644
--- a/common/utils/signal.cpp
+++ b/common/utils/signal.cpp
@@ -133,6 +133,17 @@ void signalIgnore(const std::initializer_list& signals)
}
}
+void sendSignal(const pid_t pid, const int sigNum)
+{
+ if (-1 == ::kill(pid, sigNum)) {
+ const std::string msg = "Error during killing pid: " + std::to_string(pid) +
+ " sigNum: " + std::to_string(sigNum) +
+ ": " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+}
+
} // namespace utils
diff --git a/common/utils/signal.hpp b/common/utils/signal.hpp
index 3ecf166..f4a42e3 100644
--- a/common/utils/signal.hpp
+++ b/common/utils/signal.hpp
@@ -36,6 +36,7 @@ void signalBlockAllExcept(const std::initializer_list& signals);
void signalBlock(const int sigNum);
void signalUnblock(const int sigNum);
void signalIgnore(const std::initializer_list& signals);
+void sendSignal(const pid_t pid, const int sigNum);
} // namespace utils
diff --git a/libs/lxcpp/commands/stop.cpp b/libs/lxcpp/commands/stop.cpp
new file mode 100644
index 0000000..111ef9f
--- /dev/null
+++ b/libs/lxcpp/commands/stop.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Implementation of stopping a container
+ */
+
+#include "lxcpp/commands/stop.hpp"
+#include "lxcpp/exception.hpp"
+#include "lxcpp/process.hpp"
+
+#include "logger/logger.hpp"
+#include "utils/signal.hpp"
+
+namespace lxcpp {
+
+Stop::Stop(ContainerConfig &config)
+ : mConfig(config)
+{
+}
+
+Stop::~Stop()
+{
+}
+
+void Stop::execute()
+{
+ LOGD("Stopping container: " << mConfig.mName);
+
+ // TODO: Use initctl/systemd-initctl if available in container
+
+ utils::sendSignal(mConfig.mInitPid, SIGTERM);
+}
+
+} // namespace lxcpp
diff --git a/libs/lxcpp/commands/stop.hpp b/libs/lxcpp/commands/stop.hpp
new file mode 100644
index 0000000..291a0cd
--- /dev/null
+++ b/libs/lxcpp/commands/stop.hpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Jan Olszak (j.olszak@samsung.com)
+ * @brief Implementation of stopping a container
+ */
+
+#ifndef LXCPP_COMMANDS_STOP_HPP
+#define LXCPP_COMMANDS_STOP_HPP
+
+#include "lxcpp/commands/command.hpp"
+#include "lxcpp/container-config.hpp"
+
+#include
+
+
+namespace lxcpp {
+
+
+class Stop final: Command {
+public:
+ /**
+ * Stops the container
+ *
+ * @param config container's config
+ */
+ Stop(ContainerConfig &config);
+ ~Stop();
+
+ void execute();
+
+private:
+ ContainerConfig &mConfig;
+};
+
+
+} // namespace lxcpp
+
+
+#endif // LXCPP_COMMANDS_STOP_HPP
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index 9ff4b52..d3258aa 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -29,6 +29,7 @@
#include "lxcpp/capability.hpp"
#include "lxcpp/commands/attach.hpp"
#include "lxcpp/commands/start.hpp"
+#include "lxcpp/commands/stop.hpp"
#include "lxcpp/commands/prep-host-terminal.hpp"
#include "logger/logger.hpp"
@@ -187,7 +188,8 @@ void ContainerImpl::stop()
// TODO: things to do when shuttting down the container:
// - close PTY master FDs from the config so we won't keep PTYs open
- throw NotImplementedException();
+ Stop stop(mConfig);
+ stop.execute();
}
void ContainerImpl::freeze()
diff --git a/libs/lxcpp/utils.cpp b/libs/lxcpp/utils.cpp
index 0c731b5..d0418af 100644
--- a/libs/lxcpp/utils.cpp
+++ b/libs/lxcpp/utils.cpp
@@ -54,8 +54,8 @@ void setProcTitle(const std::string &title)
// Skip the first 47 fields, entries 48-49 are ARG_START and ARG_END.
std::advance(it, 47);
- unsigned long argStart = std::stol(*it++);
- unsigned long argEnd = std::stol(*it++);
+ unsigned long argStart = std::stoul(*it++);
+ unsigned long argEnd = std::stoul(*it);
f.close();
diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp
index ff72b94..1c1a76c 100644
--- a/tests/unit_tests/lxcpp/ut-container.cpp
+++ b/tests/unit_tests/lxcpp/ut-container.cpp
@@ -109,14 +109,15 @@ BOOST_AUTO_TEST_CASE(SetLogger)
BadArgument);
}
-// BOOST_AUTO_TEST_CASE(StartStop)
-// {
-// auto c = std::unique_ptr(createContainer("StartStop", "/"));
-// BOOST_CHECK_NO_THROW(c->setInit(COMMAND));
-// BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
-// logger::LogLevel::DEBUG,
-// LOGGER_FILE));
-// BOOST_CHECK_NO_THROW(c->start());
-// }
+BOOST_AUTO_TEST_CASE(StartStop)
+{
+ auto c = std::unique_ptr(createContainer("StartStop", "/"));
+ BOOST_CHECK_NO_THROW(c->setInit(COMMAND));
+ BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
+ logger::LogLevel::DEBUG,
+ LOGGER_FILE));
+ BOOST_CHECK_NO_THROW(c->start());
+ BOOST_CHECK_NO_THROW(c->stop());
+}
BOOST_AUTO_TEST_SUITE_END()
--
2.7.4
From 046432b8d6840b9d70891caaab2c5155229e2f77 Mon Sep 17 00:00:00 2001
From: "Maciej J. Karpiuk"
Date: Mon, 12 Oct 2015 12:29:54 +0200
Subject: [PATCH 09/16] vasum: housekeeping, removal of 'using namespace std;'
[Feature] N/A
[Cause] N/A
[Solution] N/A
[Verification] N/A
Change-Id: I583b5ad44cd0d460c6b0c4db0d05217ab05cc2e4
---
cli/command-line-interface.cpp | 126 ++++++++++++++++++++---------------------
client/vasum-client-impl.cpp | 43 +++++++-------
client/vasum-client-impl.hpp | 2 +-
client/vasum-client.cpp | 4 +-
server/netdev.cpp | 69 +++++++++++-----------
5 files changed, 119 insertions(+), 125 deletions(-)
diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp
index 27d7cac..ad5400d 100644
--- a/cli/command-line-interface.cpp
+++ b/cli/command-line-interface.cpp
@@ -44,8 +44,6 @@
#include
#include
-using namespace std;
-
namespace vasum {
namespace cli {
@@ -92,23 +90,23 @@ std::string netdevToString(const VsmNetdev& netdev)
return out;
}
-typedef vector> Table;
+typedef std::vector> Table;
-ostream& operator<<(ostream& out, const Table& table)
+std::ostream& operator<<(std::ostream& out, const Table& table)
{
- vector sizes;
+ std::vector sizes;
for (const auto& row : table) {
if (sizes.size() < row.size()) {
sizes.resize(row.size());
}
for (size_t i = 0; i < row.size(); ++i) {
- sizes[i] = max(sizes[i], row[i].length());
+ sizes[i] = std::max(sizes[i], row[i].length());
}
}
for (const auto& row : table) {
for (size_t i = 0; i < row.size(); ++i) {
- out << left << setw(sizes[i]+2) << row[i];
+ out << std::left << std::setw(sizes[i]+2) << row[i];
}
out << "\n";
}
@@ -129,7 +127,7 @@ enum macvlan_mode macvlanFromString(const std::string& mode) {
if (mode == "passthru") {
return MACVLAN_MODE_PASSTHRU;
}
- throw runtime_error("Unsupported macvlan mode");
+ throw std::runtime_error("Unsupported macvlan mode");
}
void buildZoneList(std::vector& list)
@@ -144,7 +142,7 @@ void buildZoneList(std::vector& list)
vsm_array_string_free(ids);
}
-void buildNetdevList(const std::string& zone,std::vector& list)
+void buildNetdevList(const std::string& zone, std::vector& list)
{
using namespace std::placeholders;
VsmArrayString ids;
@@ -167,9 +165,9 @@ const std::vector CommandLineInterface::buildCompletionList(const A
}
ArgSpec as = mArgsSpec[a.size() - 2];
- string::size_type s = 0U;
- string::size_type e = s;
- while (e != string::npos) {
+ std::string::size_type s = 0U;
+ std::string::size_type e = s;
+ while (e != std::string::npos) {
e = as.format.find('|', s);
std::string ss = as.format.substr(s, e - s);
s = e + 1;
@@ -197,12 +195,12 @@ void CommandLineInterface::connect()
CommandLineInterface::client = vsm_client_create();
if (CommandLineInterface::client == nullptr) {
- throw runtime_error("Can't create client");
+ throw std::runtime_error("Can't create client");
}
status = vsm_connect(client);
if (VSMCLIENT_SUCCESS != status) {
- string msg = vsm_get_status_message(CommandLineInterface::client);
+ std::string msg = vsm_get_status_message(CommandLineInterface::client);
vsm_client_free(CommandLineInterface::client);
CommandLineInterface::client = nullptr;
throw IOException(msg);
@@ -211,7 +209,7 @@ void CommandLineInterface::connect()
void CommandLineInterface::disconnect()
{
- string msg;
+ std::string msg;
VsmStatus status;
if (CommandLineInterface::client == nullptr) {
@@ -227,17 +225,17 @@ void CommandLineInterface::disconnect()
CommandLineInterface::client = nullptr;
if (VSMCLIENT_SUCCESS != status) {
- throw runtime_error(msg);
+ throw std::runtime_error(msg);
}
}
-void CommandLineInterface::executeCallback(const function& fun)
+void CommandLineInterface::executeCallback(const std::function& fun)
{
CommandLineInterface::connect();
VsmStatus status = fun(CommandLineInterface::client);
if (VSMCLIENT_SUCCESS != status) {
- throw runtime_error(vsm_get_status_message(CommandLineInterface::client));
+ throw std::runtime_error(vsm_get_status_message(CommandLineInterface::client));
}
}
@@ -306,7 +304,7 @@ void set_active_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_set_active_zone, _1, argv[1].c_str()));
@@ -317,7 +315,7 @@ void create_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
if (argv.size() >= 3 && !argv[2].empty()) {
@@ -332,7 +330,7 @@ void destroy_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_destroy_zone, _1, argv[1].c_str(), 1));
@@ -343,7 +341,7 @@ void shutdown_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_shutdown_zone, _1, argv[1].c_str()));
@@ -354,7 +352,7 @@ void start_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_start_zone, _1, argv[1].c_str()));
@@ -365,7 +363,7 @@ void console_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
VsmZone zone;
@@ -373,7 +371,7 @@ void console_zone(const Args& argv)
if (zoneStateToString(vsm_zone_get_state(zone)) != "RUNNING") {
vsm_zone_free(zone);
- throw runtime_error("Zone '" + argv[1] + "' is not running");
+ throw std::runtime_error("Zone '" + argv[1] + "' is not running");
}
std::string zonesPath = vsm_zone_get_rootfs(zone);
@@ -389,7 +387,7 @@ void console_zone(const Args& argv)
.add("-P").add(zonesPath.c_str());
if (!execv("/usr/bin/lxc-console", const_cast(args.c_array()))) {
- throw runtime_error("Could not log into zone");
+ throw std::runtime_error("Could not log into zone");
}
}
@@ -398,7 +396,7 @@ void lock_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_lock_zone, _1, argv[1].c_str()));
@@ -409,7 +407,7 @@ void unlock_zone(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_unlock_zone, _1, argv[1].c_str()));
@@ -439,17 +437,17 @@ void get_zones_status(const Args& argv)
for (VsmString* id = ids; *id; ++id) {
VsmZone zone;
CommandLineInterface::executeCallback(bind(vsm_lookup_zone_by_id, _1, *id, &zone));
- assert(string(vsm_zone_get_id(zone)) == string(*id));
- table.push_back({string(vsm_zone_get_id(zone)) == string(activeId) ? "YES" : "NO",
+ assert(std::string(vsm_zone_get_id(zone)) == std::string(*id));
+ table.push_back({std::string(vsm_zone_get_id(zone)) == std::string(activeId) ? "YES" : "NO",
vsm_zone_get_id(zone),
zoneStateToString(vsm_zone_get_state(zone)),
- to_string(vsm_zone_get_terminal(zone)),
+ std::to_string(vsm_zone_get_terminal(zone)),
vsm_zone_get_rootfs(zone)});
vsm_zone_free(zone);
}
vsm_string_free(activeId);
vsm_array_string_free(ids);
- cout << table << endl;
+ std::cout << table << std::endl;
}
void get_zone_ids(const Args& /*argv*/)
@@ -458,12 +456,12 @@ void get_zone_ids(const Args& /*argv*/)
VsmArrayString ids;
CommandLineInterface::executeCallback(bind(vsm_get_zone_ids, _1, &ids));
- string delim;
+ std::string delim;
for (VsmString* id = ids; *id; ++id) {
- cout << delim << *id;
+ std::cout << delim << *id;
delim = ", ";
}
- cout << endl;
+ std::cout << std::endl;
vsm_array_string_free(ids);
}
@@ -473,7 +471,7 @@ void get_active_zone(const Args& /*argv*/)
VsmString id;
CommandLineInterface::executeCallback(bind(vsm_get_active_zone_id, _1, &id));
- cout << id << endl;
+ std::cout << id << std::endl;
vsm_string_free(id);
}
@@ -482,7 +480,7 @@ void grant_device(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
uint32_t flags = O_RDWR;
@@ -494,7 +492,7 @@ void revoke_device(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_revoke_device, _1, argv[1].c_str(), argv[2].c_str()));
@@ -505,13 +503,13 @@ void create_netdev(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
std::string nettype = argv[2];
if (nettype == "phys") {
if (argv.size() < 4) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_create_netdev_phys,
_1,
@@ -520,7 +518,7 @@ void create_netdev(const Args& argv)
}
else if (nettype == "veth") {
if (argv.size() < 5) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_create_netdev_veth,
_1,
@@ -530,7 +528,7 @@ void create_netdev(const Args& argv)
}
else if (nettype == "macvlan") {
if (argv.size() < 6) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_create_netdev_macvlan,
_1,
@@ -540,7 +538,7 @@ void create_netdev(const Args& argv)
macvlanFromString(argv[5].c_str())));
}
else
- throw runtime_error("Wrong nettype option " + nettype);
+ throw std::runtime_error("Wrong nettype option " + nettype);
}
void destroy_netdev(const Args& argv)
@@ -548,7 +546,7 @@ void destroy_netdev(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_destroy_netdev,
_1,
@@ -561,7 +559,7 @@ void netdev_list(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 2) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
if (argv.size() < 3) {
VsmArrayString ids;
@@ -569,15 +567,15 @@ void netdev_list(const Args& argv)
_1,
argv[1].c_str(),
&ids));
- string delim;
+ std::string delim;
for (VsmString* id = ids; *id; ++id) {
- cout << delim << *id;
+ std::cout << delim << *id;
delim = ", ";
}
if (delim.empty()) {
- cout << "There is no network device in zone";
+ std::cout << "There is no network device in zone";
}
- cout << endl;
+ std::cout << std::endl;
vsm_array_string_free(ids);
}
else {
@@ -588,7 +586,7 @@ void netdev_list(const Args& argv)
argv[1].c_str(),
argv[2].c_str(),
&netdev));
- cout << netdevToString(netdev) << endl;
+ std::cout << netdevToString(netdev) << std::endl;
vsm_netdev_free(netdev);
VsmAddrList addrs = NULL;
@@ -601,9 +599,9 @@ void netdev_list(const Args& argv)
for (unsigned i=0; i < listsize; ++i) {
int type=vsm_addrlist_get_type(addrs, i);
if (inet_ntop(type, vsm_addrlist_get_addr(addrs, i), buf, INET6_ADDRSTRLEN) == NULL) {
- throw runtime_error("Wrong address received ["+std::to_string(i)+"] type="+std::to_string(type));
+ throw std::runtime_error("Wrong address received ["+std::to_string(i)+"] type="+std::to_string(type));
}
- cout << buf << "/" << vsm_addrlist_get_prefix(addrs, i) << endl;
+ std::cout << buf << "/" << vsm_addrlist_get_prefix(addrs, i) << std::endl;
}
vsm_addrlist_free(addrs);
}
@@ -613,31 +611,31 @@ void netdev_add_ip_addr(const Args& argv)
{
using namespace std::placeholders;
if (argv.size() < 5) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
if (argv[3].find(':') == std::string::npos) {
in_addr addr;
if (inet_pton(AF_INET, argv[3].c_str(), &addr) != 1) {
- throw runtime_error("Wrong address format");
+ throw std::runtime_error("Wrong address format");
};
CommandLineInterface::executeCallback(bind(vsm_netdev_add_ipv4_addr,
_1,
argv[1].c_str(),
argv[2].c_str(),
&addr,
- stoi(argv[4].c_str())));
+ std::stoi(argv[4].c_str())));
}
else {
in6_addr addr;
if (inet_pton(AF_INET6, argv[3].c_str(), &addr) != 1) {
- throw runtime_error("Wrong address format");
+ throw std::runtime_error("Wrong address format");
};
CommandLineInterface::executeCallback(bind(vsm_netdev_add_ipv6_addr,
_1,
argv[1].c_str(),
argv[2].c_str(),
&addr,
- stoi(argv[4].c_str())));
+ std::stoi(argv[4].c_str())));
}
}
@@ -645,31 +643,31 @@ void netdev_del_ip_addr(const Args& argv)
{
using namespace std::placeholders;
if (argv.size() < 5) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
if (argv[3].find(':') == std::string::npos) {
in_addr addr;
if (inet_pton(AF_INET, argv[3].c_str(), &addr) != 1) {
- throw runtime_error("Wrong address format");
+ throw std::runtime_error("Wrong address format");
};
CommandLineInterface::executeCallback(bind(vsm_netdev_del_ipv4_addr,
_1,
argv[1].c_str(),
argv[2].c_str(),
&addr,
- stoi(argv[4].c_str())));
+ std::stoi(argv[4].c_str())));
}
else {
in6_addr addr;
if (inet_pton(AF_INET6, argv[3].c_str(), &addr) != 1) {
- throw runtime_error("Wrong address format");
+ throw std::runtime_error("Wrong address format");
};
CommandLineInterface::executeCallback(bind(vsm_netdev_del_ipv6_addr,
_1,
argv[1].c_str(),
argv[2].c_str(),
&addr,
- stoi(argv[4].c_str())));
+ std::stoi(argv[4].c_str())));
}
}
@@ -678,7 +676,7 @@ void netdev_up(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_netdev_up,
_1,
@@ -691,7 +689,7 @@ void netdev_down(const Args& argv)
using namespace std::placeholders;
if (argv.size() < 3) {
- throw runtime_error("Not enough parameters");
+ throw std::runtime_error("Not enough parameters");
}
CommandLineInterface::executeCallback(bind(vsm_netdev_down,
_1,
diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp
index 41cc919..30cc74c 100644
--- a/client/vasum-client-impl.cpp
+++ b/client/vasum-client-impl.cpp
@@ -49,7 +49,6 @@
#include
#include
-using namespace std;
using namespace utils;
using namespace vasum;
@@ -103,7 +102,7 @@ void convert(const api::ZoneInfoOut& info, Zone& zone)
zone = vsmZone;
}
-string toString(const in_addr* addr)
+std::string toString(const in_addr* addr)
{
char buf[INET_ADDRSTRLEN];
const char* ret = inet_ntop(AF_INET, addr, buf, INET_ADDRSTRLEN);
@@ -113,7 +112,7 @@ string toString(const in_addr* addr)
return ret;
}
-string toString(const in6_addr* addr)
+std::string toString(const in6_addr* addr)
{
char buf[INET6_ADDRSTRLEN];
const char* ret = inet_ntop(AF_INET6, addr, buf, INET6_ADDRSTRLEN);
@@ -123,9 +122,9 @@ string toString(const in6_addr* addr)
return ret;
}
-bool readFirstLineOfFile(const string& path, string& ret)
+bool readFirstLineOfFile(const std::string& path, std::string& ret)
{
- ifstream file(path);
+ std::ifstream file(path);
if (!file) {
return false;
}
@@ -146,7 +145,7 @@ Client::Status::Status()
{
}
-Client::Status::Status(VsmStatus status, const string& msg)
+Client::Status::Status(VsmStatus status, const std::string& msg)
: mVsmStatus(status), mMsg(msg)
{
}
@@ -182,7 +181,7 @@ ipc::epoll::EventPoll& Client::getEventPoll() const
}
}
-VsmStatus Client::coverException(const function& worker) noexcept
+VsmStatus Client::coverException(const std::function& worker) noexcept
{
try {
worker();
@@ -202,7 +201,7 @@ VsmStatus Client::coverException(const function& worker) noexcept
mStatus = Status(VSMCLIENT_CUSTOM_ERROR, ex.what());
} catch (const ipc::IPCException& ex) {
mStatus = Status(VSMCLIENT_IO_ERROR, ex.what());
- } catch (const exception& ex) {
+ } catch (const std::exception& ex) {
mStatus = Status(VSMCLIENT_CUSTOM_ERROR, ex.what());
}
VsmStatus ret = mStatus.mVsmStatus;
@@ -295,7 +294,7 @@ const char* Client::vsm_get_status_message() const noexcept
VsmStatus Client::vsm_get_status() const noexcept
{
- lock_guard lock(mStatusMutex);
+ std::lock_guard lock(mStatusMutex);
return mStatus.mVsmStatus;
}
@@ -354,14 +353,14 @@ VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept
return coverException([&] {
IS_SET(id);
- const string path = "/proc/" + to_string(pid) + "/cpuset";
+ const std::string path = "/proc/" + std::to_string(pid) + "/cpuset";
- string cpuset;
+ std::string cpuset;
if (!readFirstLineOfFile(path, cpuset)) {
throw InvalidArgumentException("Process not found");
}
- string zoneId;
+ std::string zoneId;
if (!parseZoneIdFromCpuSet(cpuset, zoneId)) {
throw OperationFailedException("unknown format of cpuset");
}
@@ -407,7 +406,7 @@ VsmStatus Client::vsm_create_zone(const char* id, const char* tname) noexcept
return coverException([&] {
IS_SET(id);
- string template_name = tname ? tname : "default";
+ std::string template_name = tname ? tname : "default";
mClient->callSync(
api::ipc::METHOD_CREATE_ZONE,
std::make_shared(api::CreateZoneIn{ id, template_name }),
@@ -552,7 +551,7 @@ VsmStatus Client::vsm_netdev_get_ip_addr(const char* id,
std::vector addrAttrs;
for(const auto& addrAttr : split(addrAttrs, attr.second, is_any_of(","))) {
size_t pos = addrAttr.find(":");
- if (pos == string::npos) continue;
+ if (pos == std::string::npos) continue;
if (addrAttr.substr(0, pos) == "prefixlen") {
addr.prefix = atoi(addrAttr.substr(pos + 1).c_str());
@@ -610,7 +609,7 @@ VsmStatus Client::vsm_netdev_add_ipv4_addr(const char* id,
IS_SET(netdevId);
IS_SET(addr);
- string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix);
+ std::string value = "ip:" + toString(addr) + ",""prefixlen:" + std::to_string(prefix);
mClient->callSync(
api::ipc::METHOD_SET_NETDEV_ATTRS,
std::make_shared(
@@ -628,7 +627,7 @@ VsmStatus Client::vsm_netdev_add_ipv6_addr(const char* id,
IS_SET(netdevId);
IS_SET(addr);
- string value = "ip:" + toString(addr) + ",""prefixlen:" + to_string(prefix);
+ std::string value = "ip:" + toString(addr) + ",""prefixlen:" + std::to_string(prefix);
mClient->callSync(
api::ipc::METHOD_SET_NETDEV_ATTRS,
std::make_shared(
@@ -647,7 +646,7 @@ VsmStatus Client::vsm_netdev_del_ipv4_addr(const char* id,
IS_SET(addr);
//CIDR notation
- string ip = toString(addr) + "/" + to_string(prefix);
+ std::string ip = toString(addr) + "/" + std::to_string(prefix);
mClient->callSync(
api::ipc::METHOD_DELETE_NETDEV_IP_ADDRESS,
std::make_shared(
@@ -666,7 +665,7 @@ VsmStatus Client::vsm_netdev_del_ipv6_addr(const char* id,
IS_SET(addr);
//CIDR notation
- string ip = toString(addr) + "/" + to_string(prefix);
+ std::string ip = toString(addr) + "/" + std::to_string(prefix);
mClient->callSync(
api::ipc::METHOD_DELETE_NETDEV_IP_ADDRESS,
std::make_shared(
@@ -684,8 +683,8 @@ VsmStatus Client::vsm_netdev_up(const char* id, const char* netdevId) noexcept
mClient->callSync(
api::ipc::METHOD_SET_NETDEV_ATTRS,
std::make_shared(
- api::SetNetDevAttrsIn{ id, netdevId, { { "flags", to_string(IFF_UP) },
- { "change", to_string(IFF_UP) } } }));
+ api::SetNetDevAttrsIn{ id, netdevId, { { "flags", std::to_string(IFF_UP) },
+ { "change", std::to_string(IFF_UP) } } }));
});
}
@@ -698,8 +697,8 @@ VsmStatus Client::vsm_netdev_down(const char* id, const char* netdevId) noexcept
mClient->callSync(
api::ipc::METHOD_SET_NETDEV_ATTRS,
std::make_shared(
- api::SetNetDevAttrsIn{ id, netdevId, { { "flags", to_string(~IFF_UP) },
- { "change", to_string(IFF_UP) } } }));
+ api::SetNetDevAttrsIn{ id, netdevId, { { "flags", std::to_string(~IFF_UP) },
+ { "change", std::to_string(IFF_UP) } } }));
});
}
diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp
index dbc9001..7278e68 100644
--- a/client/vasum-client-impl.hpp
+++ b/client/vasum-client-impl.hpp
@@ -81,7 +81,7 @@ typedef struct {
*
* Client uses dbus API.
*/
-class Client {
+class Client final {
public:
Client() noexcept;
~Client() noexcept;
diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp
index 9cf15b3..ccc21d5 100644
--- a/client/vasum-client.cpp
+++ b/client/vasum-client.cpp
@@ -33,8 +33,6 @@
#define API __attribute__((visibility("default")))
#endif // API
-using namespace std;
-
namespace {
Client& getClient(VsmClient client)
@@ -77,7 +75,7 @@ API VsmStatus vsm_get_dispatcher_type(VsmClient client, VsmDispacherType* dispac
API VsmClient vsm_client_create()
{
- Client* clientPtr = new(nothrow) Client();
+ Client* clientPtr = new(std::nothrow) Client();
return reinterpret_cast(clientPtr);
}
diff --git a/server/netdev.cpp b/server/netdev.cpp
index 8387c84..9565ed3 100644
--- a/server/netdev.cpp
+++ b/server/netdev.cpp
@@ -63,18 +63,18 @@
#define BRIDGE_FLAGS_MASTER 1
#endif
-using namespace std;
using namespace utils;
using namespace vasum::netlink;
+using std::get;
namespace vasum {
namespace netdev {
namespace {
-string getUniqueVethName()
+std::string getUniqueVethName()
{
- auto find = [](const ifaddrs* ifaddr, const string& name) -> bool {
+ auto find = [](const ifaddrs* ifaddr, const std::string& name) -> bool {
for (const ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (name == ifa->ifa_name) {
return true;
@@ -85,17 +85,17 @@ string getUniqueVethName()
ifaddrs* ifaddr;
getifaddrs(&ifaddr);
- string newName;
+ std::string newName;
int i = 0;
do {
- newName = "veth0" + to_string(++i);
+ newName = "veth0" + std::to_string(++i);
} while (find(ifaddr, newName));
freeifaddrs(ifaddr);
return newName;
}
-uint32_t getInterfaceIndex(const string& name) {
+uint32_t getInterfaceIndex(const std::string& name) {
uint32_t index = if_nametoindex(name.c_str());
if (!index) {
const std::string msg = "Can't get " + name + " interface index (" + getSystemErrorMessage() + ")";
@@ -105,7 +105,7 @@ uint32_t getInterfaceIndex(const string& name) {
return index;
}
-uint32_t getInterfaceIndex(const string& name, pid_t nsPid) {
+uint32_t getInterfaceIndex(const std::string& name, pid_t nsPid) {
NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST | NLM_F_ACK);
ifinfomsg infoPeer = utils::make_clean();
infoPeer.ifi_family = AF_UNSPEC;
@@ -126,14 +126,14 @@ int getIpFamily(const std::string& ip)
return ip.find(':') == std::string::npos ? AF_INET : AF_INET6;
}
-void validateNetdevName(const string& name)
+void validateNetdevName(const std::string& name)
{
if (name.size() <= 1 || name.size() >= IFNAMSIZ) {
throw ZoneOperationException("Invalid netdev name format");
}
}
-void createPipedNetdev(const string& netdev1, const string& netdev2)
+void createPipedNetdev(const std::string& netdev1, const std::string& netdev2)
{
validateNetdevName(netdev1);
validateNetdevName(netdev2);
@@ -156,7 +156,7 @@ void createPipedNetdev(const string& netdev1, const string& netdev2)
send(nlm);
}
-void attachToBridge(const string& bridge, const string& netdev)
+void attachToBridge(const std::string& bridge, const std::string& netdev)
{
validateNetdevName(bridge);
validateNetdevName(netdev);
@@ -184,7 +184,7 @@ void attachToBridge(const string& bridge, const string& netdev)
close(fd);
}
-int setFlags(const string& name, uint32_t mask, uint32_t flags)
+int setFlags(const std::string& name, uint32_t mask, uint32_t flags)
{
uint32_t index = getInterfaceIndex(name);
NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
@@ -199,12 +199,12 @@ int setFlags(const string& name, uint32_t mask, uint32_t flags)
return 0;
}
-void up(const string& netdev)
+void up(const std::string& netdev)
{
setFlags(netdev, IFF_UP, IFF_UP);
}
-void moveToNS(const string& netdev, pid_t pid)
+void moveToNS(const std::string& netdev, pid_t pid)
{
uint32_t index = getInterfaceIndex(netdev);
NetlinkMessage nlm(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_ACK);
@@ -216,7 +216,7 @@ void moveToNS(const string& netdev, pid_t pid)
send(nlm);
}
-void createMacvlan(const string& master, const string& slave, const macvlan_mode& mode)
+void createMacvlan(const std::string& master, const std::string& slave, const macvlan_mode& mode)
{
validateNetdevName(master);
validateNetdevName(slave);
@@ -283,7 +283,7 @@ std::vector getIpAddresses(const pid_t nsPid, int family, uint32_t index)
LOGE(msg);
throw VasumException(msg);
}
- attrs.push_back(make_tuple("ip", buf));
+ attrs.push_back(std::make_tuple("ip", buf));
break;
default:
response.skipAttribute();
@@ -372,19 +372,19 @@ void deleteIpAddress(const pid_t nsPid,
} // namespace
-void createVeth(const pid_t& nsPid, const string& nsDev, const string& hostDev)
+void createVeth(const pid_t& nsPid, const std::string& nsDev, const std::string& hostDev)
{
- string hostVeth = getUniqueVethName();
+ std::string hostVeth = getUniqueVethName();
LOGT("Creating veth: bridge: " << hostDev << ", port: " << hostVeth << ", zone: " << nsDev);
createPipedNetdev(nsDev, hostVeth);
try {
attachToBridge(hostDev, hostVeth);
up(hostVeth);
moveToNS(nsDev, nsPid);
- } catch(const exception& ex) {
+ } catch(const std::exception& ex) {
try {
destroyNetdev(hostVeth);
- } catch (const exception& ex) {
+ } catch (const std::exception& ex) {
LOGE("Can't destroy netdev pipe: " << hostVeth << ", " << nsDev);
}
throw;
@@ -392,8 +392,8 @@ void createVeth(const pid_t& nsPid, const string& nsDev, const string& hostDev)
}
void createMacvlan(const pid_t& nsPid,
- const string& nsDev,
- const string& hostDev,
+ const std::string& nsDev,
+ const std::string& hostDev,
const macvlan_mode& mode)
{
LOGT("Creating macvlan: host: " << hostDev << ", zone: " << nsDev << ", mode: " << mode);
@@ -401,17 +401,17 @@ void createMacvlan(const pid_t& nsPid,
try {
up(nsDev);
moveToNS(nsDev, nsPid);
- } catch(const exception& ex) {
+ } catch(const std::exception& ex) {
try {
destroyNetdev(nsDev);
- } catch (const exception& ex) {
+ } catch (const std::exception& ex) {
LOGE("Can't destroy netdev: " << nsDev);
}
throw;
}
}
-void movePhys(const pid_t& nsPid, const string& devId)
+void movePhys(const pid_t& nsPid, const std::string& devId)
{
LOGT("Creating phys: dev: " << devId);
moveToNS(devId, nsPid);
@@ -437,7 +437,7 @@ std::vector listNetdev(const pid_t& nsPid)
return interfaces;
}
-void destroyNetdev(const string& netdev, const pid_t pid)
+void destroyNetdev(const std::string& netdev, const pid_t pid)
{
LOGT("Destroying netdev: " << netdev);
validateNetdevName(netdev);
@@ -451,7 +451,7 @@ void destroyNetdev(const string& netdev, const pid_t pid)
send(nlm, pid);
}
-void createBridge(const string& netdev)
+void createBridge(const std::string& netdev)
{
LOGT("Creating bridge: " << netdev);
validateNetdevName(netdev);
@@ -477,7 +477,7 @@ Attrs getAttrs(const pid_t nsPid, const std::string& netdev)
{
auto joinAddresses = [](const Attrs& attrs) -> std::string {
bool first = true;
- stringstream ss;
+ std::stringstream ss;
for (const auto& attr : attrs) {
ss << (first ? "" : ",") << get<0>(attr) << ":" << get<1>(attr);
first = false;
@@ -539,7 +539,7 @@ Attrs getAttrs(const pid_t nsPid, const std::string& netdev)
void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs)
{
- const set supportedAttrs{"flags", "change", "type", "mtu", "link", "ipv4", "ipv6"};
+ const std::set supportedAttrs{"flags", "change", "type", "mtu", "link", "ipv4", "ipv6"};
LOGT("Setting network device informations: " << netdev);
validateNetdevName(netdev);
@@ -581,8 +581,8 @@ void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs)
}
//TODO: Multiple addresses should be set at once (add support NLM_F_MULTI to NetlinkMessage).
- vector ipv4;
- vector ipv6;
+ std::vector ipv4;
+ std::vector ipv6;
for (const auto& attr : attrs) {
if (get<0>(attr) == "ipv4") {
ipv4.push_back(get<1>(attr));
@@ -592,14 +592,14 @@ void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs)
}
}
- auto setIp = [nsPid](const vector& ips, uint32_t index, int family) -> void {
+ auto setIp = [nsPid](const std::vector& ips, uint32_t index, int family) -> void {
using namespace boost::algorithm;
for (const auto& ip : ips) {
Attrs attrs;
- vector params;
+ std::vector params;
for (const auto& addrAttr : split(params, ip, is_any_of(","))) {
size_t pos = addrAttr.find(":");
- if (pos == string::npos || pos == addrAttr.length()) {
+ if (pos == std::string::npos || pos == addrAttr.length()) {
const std::string msg = "Wrong input data format: ill formed address attribute: " + addrAttr;
LOGE(msg);
throw VasumException(msg);
@@ -620,7 +620,7 @@ void deleteIpAddress(const pid_t nsPid,
{
uint32_t index = getInterfaceIndex(netdev, nsPid);
size_t slash = ip.find('/');
- if (slash == string::npos) {
+ if (slash == std::string::npos) {
const std::string msg = "Wrong address format: it is not CIDR notation: can't find '/'";
LOGE(msg);
throw VasumException(msg);
@@ -639,4 +639,3 @@ void deleteIpAddress(const pid_t nsPid,
} //namespace netdev
} //namespace vasum
-
--
2.7.4
From 732fd0b180e78e53b791c18dc39a18f1fa8e8e30 Mon Sep 17 00:00:00 2001
From: Jan Olszak
Date: Mon, 12 Oct 2015 17:45:21 +0200
Subject: [PATCH 10/16] lxcpp: Adding init process to UTS, PID, NET, IPC
namespaces
[Feature] Starting init in some namespaces.
MNT and USER need more work.
[Cause] N/A
[Solution] Refactored Guard
[Verification] Build, install and run tests
Change-Id: I3c5ec5c833da34c9ece6acf2c4965e8c57ab966d
---
libs/lxcpp/container-config.hpp | 13 +++++-
libs/lxcpp/container-impl.cpp | 6 ++-
libs/lxcpp/container-impl.hpp | 1 +
libs/lxcpp/container.hpp | 2 +
libs/lxcpp/guard/guard.cpp | 73 ++++++++++++++++++---------------
libs/lxcpp/guard/guard.hpp | 11 ++++-
libs/lxcpp/guard/main.cpp | 11 +++--
tests/unit_tests/lxcpp/ut-container.cpp | 1 +
8 files changed, 78 insertions(+), 40 deletions(-)
diff --git a/libs/lxcpp/container-config.hpp b/libs/lxcpp/container-config.hpp
index c84b4ef..9990bdc 100644
--- a/libs/lxcpp/container-config.hpp
+++ b/libs/lxcpp/container-config.hpp
@@ -109,7 +109,15 @@ struct ContainerConfig {
*/
TerminalsConfig mTerminals;
- ContainerConfig() : mGuardPid(-1), mInitPid(-1) {}
+ /**
+ * Namespace types used to create the container
+ *
+ * Set: setNamespaces()
+ * Get: none
+ */
+ int mNamespaces;
+
+ ContainerConfig() : mGuardPid(-1), mInitPid(-1), mNamespaces(0) {}
CONFIG_REGISTER
(
@@ -119,7 +127,8 @@ struct ContainerConfig {
mInitPid,
mInit,
mLogger,
- mTerminals
+ mTerminals,
+ mNamespaces
)
};
diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp
index d3258aa..5f0da35 100644
--- a/libs/lxcpp/container-impl.cpp
+++ b/libs/lxcpp/container-impl.cpp
@@ -25,7 +25,6 @@
#include "lxcpp/exception.hpp"
#include "lxcpp/process.hpp"
#include "lxcpp/filesystem.hpp"
-#include "lxcpp/namespace.hpp"
#include "lxcpp/capability.hpp"
#include "lxcpp/commands/attach.hpp"
#include "lxcpp/commands/start.hpp"
@@ -169,6 +168,11 @@ void ContainerImpl::setTerminalCount(const unsigned int count)
mConfig.mTerminals.count = count;
}
+void ContainerImpl::setNamespaces(const int namespaces)
+{
+ mConfig.mNamespaces = namespaces;
+}
+
void ContainerImpl::start()
{
// TODO: check config consistency and completeness somehow
diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp
index 041303b..846536e 100644
--- a/libs/lxcpp/container-impl.hpp
+++ b/libs/lxcpp/container-impl.hpp
@@ -56,6 +56,7 @@ public:
void setTerminalCount(const unsigned int count);
const std::vector& getNamespaces() const;
+ void setNamespaces(const int namespaces);
// Execution actions
void start();
diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp
index e3d537f..ba32e64 100644
--- a/libs/lxcpp/container.hpp
+++ b/libs/lxcpp/container.hpp
@@ -26,6 +26,7 @@
#include "lxcpp/network-config.hpp"
#include "lxcpp/logger-config.hpp"
+
#include
#include
@@ -62,6 +63,7 @@ public:
const std::string &arg = "") = 0;
virtual void setTerminalCount(const unsigned int count) = 0;
+ virtual void setNamespaces(const int namespaces) = 0;
// Execution actions
virtual void start() = 0;
diff --git a/libs/lxcpp/guard/guard.cpp b/libs/lxcpp/guard/guard.cpp
index 28e572a..4f56771 100644
--- a/libs/lxcpp/guard/guard.cpp
+++ b/libs/lxcpp/guard/guard.cpp
@@ -32,64 +32,71 @@
#include
#include
-
namespace lxcpp {
+namespace {
-void startContainer(const ContainerConfig &cfg)
+int startContainer(void* data)
{
- lxcpp::execve(cfg.mInit);
+ ContainerConfig& config = *static_cast(data);
+
+ // TODO: container preparation part 2
+
+ PrepGuestTerminal terminals(config.mTerminals);
+ terminals.execute();
+
+ lxcpp::execve(config.mInit);
+
+ return EXIT_FAILURE;
}
-int startGuard(int channelFD)
+} // namespace
+
+
+Guard::Guard(const int channelFD)
+ : mChannel(channelFD)
{
- ContainerConfig cfg;
- utils::Channel channel(channelFD);
- channel.setCloseOnExec(true);
- config::loadFromFD(channel.getFD(), cfg);
+ mChannel.setCloseOnExec(true);
+ config::loadFromFD(mChannel.getFD(), mConfig);
- logger::setupLogger(cfg.mLogger.getType(),
- cfg.mLogger.getLevel(),
- cfg.mLogger.getArg());
+ logger::setupLogger(mConfig.mLogger.getType(),
+ mConfig.mLogger.getLevel(),
+ mConfig.mLogger.getArg());
- LOGD("Guard started, config & logging restored");
+ LOGD("Config & logging restored");
try {
LOGD("Setting the guard process title");
- const std::string title = "[LXCPP] " + cfg.mName + " " + cfg.mRootPath;
+ const std::string title = "[LXCPP] " + mConfig.mName + " " + mConfig.mRootPath;
setProcTitle(title);
} catch (std::exception &e) {
// Ignore, this is optional
LOGW("Failed to set the guard process title: " << e.what());
}
+}
- // TODO: container preparation part 1
-
- // TODO: switch to clone
- LOGD("Forking container's init process");
- pid_t pid = lxcpp::fork();
-
- if (pid == 0) {
- // TODO: container preparation part 2
+Guard::~Guard()
+{
+}
- PrepGuestTerminal terminals(cfg.mTerminals);
- terminals.execute();
+int Guard::execute()
+{
+ // TODO: container preparation part 1
- startContainer(cfg);
- ::_exit(EXIT_FAILURE);
- }
+ const pid_t initPid = lxcpp::clone(startContainer,
+ &mConfig,
+ mConfig.mNamespaces);
- cfg.mGuardPid = ::getpid();
- cfg.mInitPid = pid;
+ mConfig.mGuardPid = ::getpid();
+ mConfig.mInitPid = initPid;
- channel.write(cfg.mGuardPid);
- channel.write(cfg.mInitPid);
- channel.shutdown();
+ mChannel.write(mConfig.mGuardPid);
+ mChannel.write(mConfig.mInitPid);
+ mChannel.shutdown();
- int status = lxcpp::waitpid(pid);
+ int status = lxcpp::waitpid(initPid);
LOGD("Init exited with status: " << status);
return status;
}
-
} // namespace lxcpp
diff --git a/libs/lxcpp/guard/guard.hpp b/libs/lxcpp/guard/guard.hpp
index 78457ae..741d72a 100644
--- a/libs/lxcpp/guard/guard.hpp
+++ b/libs/lxcpp/guard/guard.hpp
@@ -28,11 +28,20 @@
#include "lxcpp/container-config.hpp"
#include "utils/channel.hpp"
+
namespace lxcpp {
+class Guard {
+public:
+ Guard(const int channelFD);
+ ~Guard();
-int startGuard(int channelFD);
+ int execute();
+private:
+ utils::Channel mChannel;
+ ContainerConfig mConfig;
+};
} // namespace lxcpp
diff --git a/libs/lxcpp/guard/main.cpp b/libs/lxcpp/guard/main.cpp
index 78c7476..ff26418 100644
--- a/libs/lxcpp/guard/main.cpp
+++ b/libs/lxcpp/guard/main.cpp
@@ -35,8 +35,6 @@ int main(int argc, char *argv[])
::_exit(EXIT_FAILURE);
}
- int channelFD = std::stoi(argv[1]);
-
// NOTE: this might not be required now, but I leave it here not to forget.
// We need to investigate this with vasum and think about possibility of
// poorly written software that leaks file descriptors and might use LXCPP.
@@ -48,5 +46,12 @@ int main(int argc, char *argv[])
}
#endif
- return lxcpp::startGuard(channelFD);
+ try {
+ int fd = std::stoi(argv[1]);
+ lxcpp::Guard guard(fd);
+ return guard.execute();
+ } catch(std::exception& e) {
+ // LOGE("Unexpected: " << utils::getTypeName(e) << ": " << e.what());
+ return EXIT_FAILURE;
+ }
}
diff --git a/tests/unit_tests/lxcpp/ut-container.cpp b/tests/unit_tests/lxcpp/ut-container.cpp
index 1c1a76c..17eee93 100644
--- a/tests/unit_tests/lxcpp/ut-container.cpp
+++ b/tests/unit_tests/lxcpp/ut-container.cpp
@@ -116,6 +116,7 @@ BOOST_AUTO_TEST_CASE(StartStop)
BOOST_CHECK_NO_THROW(c->setLogger(logger::LogType::LOG_PERSISTENT_FILE,
logger::LogLevel::DEBUG,
LOGGER_FILE));
+ BOOST_CHECK_NO_THROW(c->setNamespaces(CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWUTS));
BOOST_CHECK_NO_THROW(c->start());
BOOST_CHECK_NO_THROW(c->stop());
}
--
2.7.4
From fdd084637d80bc804cced5e846158e8ac31c2252 Mon Sep 17 00:00:00 2001
From: Lukasz Pawelczyk
Date: Thu, 8 Oct 2015 13:28:31 +0200
Subject: [PATCH 11/16] Implement Container::console()
[Feature] An ability to connect to a PTY given to the container
[Cause] To be able to use the container
[Solution] Use PTYs, connect to them and pass read/writes between
stdin/stdout and pty master.
[Verification] There is a simple test program in junk for now
Additional changes with patchset:
- extended signal functions
- fixed signalFD class
Change-Id: Ia6320ee32d537311ef2675eb79f3e837192251b8
---
common/utils/signal.cpp | 87 ++++++++-
common/utils/signal.hpp | 9 +-
common/utils/signalfd.cpp | 58 +++---
common/utils/signalfd.hpp | 14 +-
junk/Makefile | 19 ++
junk/run-shell.cpp | 81 ++++++++
libs/ipc/epoll/event-poll.cpp | 2 +-
libs/lxcpp/CMakeLists.txt | 4 +-
libs/lxcpp/commands/console.cpp | 292 ++++++++++++++++++++++++++++
libs/lxcpp/commands/console.hpp | 97 +++++++++
libs/lxcpp/commands/prep-guest-terminal.cpp | 1 -
libs/lxcpp/commands/prep-host-terminal.cpp | 4 +-
libs/lxcpp/commands/prep-host-terminal.hpp | 4 +-
libs/lxcpp/container-impl.cpp | 33 +---
libs/lxcpp/container-impl.hpp | 1 +
libs/lxcpp/container.hpp | 1 +
libs/lxcpp/terminal-config.hpp | 4 +-
libs/lxcpp/terminal.cpp | 36 ++--
libs/lxcpp/terminal.hpp | 15 +-
server/server.cpp | 4 +-
tests/unit_tests/utils/ut-signalfd.cpp | 4 +-
21 files changed, 668 insertions(+), 102 deletions(-)
create mode 100644 junk/Makefile
create mode 100644 junk/run-shell.cpp
create mode 100644 libs/lxcpp/commands/console.cpp
create mode 100644 libs/lxcpp/commands/console.hpp
diff --git a/common/utils/signal.cpp b/common/utils/signal.cpp
index 51c45b1..d961879 100644
--- a/common/utils/signal.cpp
+++ b/common/utils/signal.cpp
@@ -48,13 +48,13 @@ void setSignalMask(int how, const ::sigset_t& set)
void changeSignal(int how, const int sigNum) {
::sigset_t set;
if(-1 == ::sigemptyset(&set)) {
- const std::string msg = "Error in sigfillset: " + getSystemErrorMessage();
+ const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
LOGE(msg);
throw UtilsException(msg);
}
if(-1 ==::sigaddset(&set, sigNum)) {
- const std::string msg = "Error in sigdelset: " + getSystemErrorMessage();
+ const std::string msg = "Error in sigaddset: " + getSystemErrorMessage();
LOGE(msg);
throw UtilsException(msg);
}
@@ -76,6 +76,62 @@ void changeSignal(int how, const int sigNum) {
return set;
}
+bool isSignalPending(const int sigNum)
+{
+ ::sigset_t set;
+ if (::sigpending(&set) == -1) {
+ const std::string msg = "Error in sigpending: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ int ret = ::sigismember(&set, sigNum);
+ if (ret == -1) {
+ const std::string msg = "Error in sigismember: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ return ret;
+}
+
+bool waitForSignal(const int sigNum, int timeoutMs)
+{
+ int timeoutS = timeoutMs / 1000;
+ timeoutMs -= timeoutS * 1000;
+
+ struct ::timespec timeout = {
+ timeoutS,
+ timeoutMs * 1000000
+ };
+
+ ::sigset_t set;
+ if(-1 == ::sigemptyset(&set)) {
+ const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ if(-1 ==::sigaddset(&set, sigNum)) {
+ const std::string msg = "Error in sigaddset: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ ::siginfo_t info;
+ if (::sigtimedwait(&set, &info, &timeout) == -1) {
+ if (errno == EAGAIN) {
+ return false;
+ }
+
+ const std::string msg = "Error in sigtimedwait: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ return true;
+}
+
bool isSignalBlocked(const int sigNum)
{
::sigset_t set = getSignalMask();
@@ -119,18 +175,36 @@ void signalUnblock(const int sigNum)
changeSignal(SIG_UNBLOCK, sigNum);
}
-void signalIgnore(const std::initializer_list& signals)
+std::vector> signalIgnore(const std::initializer_list& signals)
{
struct ::sigaction act;
+ struct ::sigaction old;
act.sa_handler = SIG_IGN;
+ std::vector> oldAct;
for(const int s: signals) {
- if(-1 == ::sigaction(s, &act, nullptr)) {
+ if(-1 == ::sigaction(s, &act, &old)) {
const std::string msg = "Error in sigaction: " + getSystemErrorMessage();
LOGE(msg);
throw UtilsException(msg);
}
+ oldAct.emplace_back(s, old);
}
+
+ return oldAct;
+}
+
+struct ::sigaction signalSet(const int sigNum, const struct ::sigaction *sigAct)
+{
+ struct ::sigaction old;
+
+ if(-1 == ::sigaction(sigNum, sigAct, &old)) {
+ const std::string msg = "Error in sigaction: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
+
+ return old;
}
void sendSignal(const pid_t pid, const int sigNum)
@@ -145,8 +219,3 @@ void sendSignal(const pid_t pid, const int sigNum)
}
} // namespace utils
-
-
-
-
-
diff --git a/common/utils/signal.hpp b/common/utils/signal.hpp
index f4a42e3..cb64419 100644
--- a/common/utils/signal.hpp
+++ b/common/utils/signal.hpp
@@ -27,17 +27,24 @@
#include
#include
+#include
+
namespace utils {
+
::sigset_t getSignalMask();
+bool isSignalPending(const int sigNum);
+bool waitForSignal(const int sigNum, int timeoutMs);
bool isSignalBlocked(const int sigNum);
void signalBlockAllExcept(const std::initializer_list& signals);
void signalBlock(const int sigNum);
void signalUnblock(const int sigNum);
-void signalIgnore(const std::initializer_list& signals);
+std::vector> signalIgnore(const std::initializer_list& signals);
+struct ::sigaction signalSet(const int sigNum, const struct ::sigaction *sigAct);
void sendSignal(const pid_t pid, const int sigNum);
+
} // namespace utils
diff --git a/common/utils/signalfd.cpp b/common/utils/signalfd.cpp
index 61d04d5..0156532 100644
--- a/common/utils/signalfd.cpp
+++ b/common/utils/signalfd.cpp
@@ -35,9 +35,14 @@ namespace utils {
SignalFD::SignalFD(ipc::epoll::EventPoll& eventPoll)
:mEventPoll(eventPoll)
{
- ::sigset_t set = getSignalMask();
+ int error = ::sigemptyset(&mSet);
+ if (error == -1) {
+ const std::string msg = "Error in sigemptyset: " + getSystemErrorMessage();
+ LOGE(msg);
+ throw UtilsException(msg);
+ }
- mFD = ::signalfd(-1, &set, SFD_CLOEXEC);
+ mFD = ::signalfd(-1, &mSet, SFD_CLOEXEC);
if (mFD == -1) {
const std::string msg = "Error in signalfd: " + getSystemErrorMessage();
LOGE(msg);
@@ -51,6 +56,20 @@ SignalFD::~SignalFD()
{
mEventPoll.removeFD(mFD);
utils::close(mFD);
+
+ // Unblock the signals that have been blocked previously, but also eat
+ // them if they were pending. It seems that signals are delivered twice,
+ // independently for signalfd and async. If we don't eat them before
+ // unblocking they will be delivered immediately potentially doing harm.
+ for (const int sigNum : mBlockedSignals) {
+ waitForSignal(sigNum, 0);
+
+ // Yes, there is a race here between waitForSignal and signalUnlock, but if
+ // a signal is sent at this point it's not by us, signalFD is inactive. So
+ // if that is the case I'd expect someone to have set some handler already.
+
+ signalUnblock(sigNum);
+ }
}
int SignalFD::getFD() const
@@ -62,35 +81,30 @@ void SignalFD::setHandler(const int sigNum, const Callback&& callback)
{
Lock lock(mMutex);
- ::sigset_t set = getSignalMask();
-
- int error = ::signalfd(mFD, &set, SFD_CLOEXEC);
- if (error != mFD) {
- const std::string msg = "Error in signalfd: " + getSystemErrorMessage();
- LOGE(msg);
- throw UtilsException(msg);
- }
-
- mCallbacks.insert({sigNum, callback});
-}
-
-void SignalFD::setHandlerAndBlock(const int sigNum, const Callback&& callback)
-{
- Lock lock(mMutex);
-
bool isBlocked = isSignalBlocked(sigNum);
-
- ::sigset_t set = getSignalMask();
if(!isBlocked) {
signalBlock(sigNum);
+ mBlockedSignals.push_back(sigNum);
+ }
+
+ int error = ::sigaddset(&mSet, sigNum);
+ if (error == -1) {
+ const std::string msg = getSystemErrorMessage();
+ LOGE("Error in signalfd: " << msg);
+ if(!isBlocked) {
+ signalUnblock(sigNum);
+ mBlockedSignals.pop_back();
+ }
+ throw UtilsException("Error in signalfd: " + msg);
}
- int error = ::signalfd(mFD, &set, SFD_CLOEXEC);
+ error = ::signalfd(mFD, &mSet, SFD_CLOEXEC);
if (error != mFD) {
const std::string msg = getSystemErrorMessage();
LOGE("Error in signalfd: " << msg);
if(!isBlocked) {
signalUnblock(sigNum);
+ mBlockedSignals.pop_back();
}
throw UtilsException("Error in signalfd: " + msg);
}
@@ -103,7 +117,7 @@ void SignalFD::handleInternal()
signalfd_siginfo sigInfo;
utils::read(mFD, &sigInfo, sizeof(sigInfo));
- LOGD("Got signal: " << sigInfo.ssi_signo);
+ LOGT("Got signal: " << sigInfo.ssi_signo);
{
Lock lock(mMutex);
diff --git a/common/utils/signalfd.hpp b/common/utils/signalfd.hpp
index 4efed4b..cc72ed9 100644
--- a/common/utils/signalfd.hpp
+++ b/common/utils/signalfd.hpp
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
namespace utils {
@@ -55,7 +56,7 @@ public:
/**
* Add a callback for a specified signal.
- * Doesn't block the signal.
+ * Blocks the async signal handler if it's not already blocked.
*
* @param sigNum number of the signal
* @param callback handler callback
@@ -63,15 +64,6 @@ public:
void setHandler(const int sigNum, const Callback&& callback);
/**
- * Add a callback for a specified signal
- * Blocks the asynchronous signal handling.
- *
- * @param sigNum number of the signal
- * @param callback handler callback
- */
- void setHandlerAndBlock(const int sigNum, const Callback&& callback);
-
- /**
* @return signal file descriptor
*/
int getFD() const;
@@ -80,9 +72,11 @@ private:
typedef std::unique_lock Lock;
int mFD;
+ ::sigset_t mSet;
std::mutex mMutex;
ipc::epoll::EventPoll& mEventPoll;
std::unordered_map mCallbacks;
+ std::vector mBlockedSignals;
void handleInternal();
};
diff --git a/junk/Makefile b/junk/Makefile
new file mode 100644
index 0000000..4b93782
--- /dev/null
+++ b/junk/Makefile
@@ -0,0 +1,19 @@
+C=clang
+CPP=clang++
+NAME1=run-shell
+CPPFLAGS=$(shell PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/ pkg-config --cflags liblxcpp libLogger) -g -std=c++11
+LDFLAGS=$(shell PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/ pkg-config --libs liblxcpp libLogger) -g
+
+OBJECTS1=$(NAME1).o
+HEADERS=
+
+all: $(NAME1)
+
+%.o: %.cpp $(HEADERS)
+ $(CPP) -c -o $@ $< $(CPPFLAGS)
+
+$(NAME1): $(OBJECTS1)
+ $(CPP) $(OBJECTS1) $(LDFLAGS) -o $(NAME1)
+
+clean:
+ rm -f $(OBJECTS1) $(NAME1)
diff --git a/junk/run-shell.cpp b/junk/run-shell.cpp
new file mode 100644
index 0000000..81ee0d8
--- /dev/null
+++ b/junk/run-shell.cpp
@@ -0,0 +1,81 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace lxcpp;
+
+pid_t initPid = -1;
+
+void sighandler(int signal)
+{
+ // remove the log in a deffered manner
+ pid_t pid = fork();
+
+ if (pid == 0)
+ {
+ pid_t pid = fork();
+
+ if (pid == 0)
+ {
+ if (initPid > 0)
+ ::kill(initPid, SIGTERM);
+ sleep(11);
+ ::unlink("/tmp/lxcpp-shell.txt");
+
+ exit(0);
+ }
+
+ exit(0);
+ }
+
+ wait();
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ signal(SIGINT, &sighandler);
+
+ logger::setupLogger(logger::LogType::LOG_STDERR, logger::LogLevel::TRACE);
+ LOGT("Color test: TRACE");
+ LOGD("Color test: DEBUG");
+ LOGI("Color test: INFO");
+ LOGW("Color test: WARN");
+ LOGE("Color test: ERROR");
+
+ logger::setupLogger(logger::LogType::LOG_STDERR, logger::LogLevel::DEBUG);
+ //logger::setupLogger(logger::LogType::LOG_FILE, logger::LogLevel::TRACE, "/tmp/lxcpp-shell.txt");
+
+ std::vector args;
+ args.push_back("/bin/bash");
+
+ try
+ {
+ Container* c = createContainer("test", "/");
+ c->setInit(args);
+ c->setLogger(logger::LogType::LOG_FILE, logger::LogLevel::TRACE, "/tmp/lxcpp-shell.txt");
+ c->setTerminalCount(4);
+ c->start();
+ c->console();
+ // You could run the console for the second time to see if it can be reattached
+ //c->console();
+
+ initPid = c->getInitPid();
+
+ delete c;
+ }
+ catch (const std::exception &e)
+ {
+ std::cout << "EXCEPTION: " << e.what() << std::endl;
+ }
+
+ sighandler(3);
+
+ return 0;
+}
diff --git a/libs/ipc/epoll/event-poll.cpp b/libs/ipc/epoll/event-poll.cpp
index c4b1f40..8fe41b2 100644
--- a/libs/ipc/epoll/event-poll.cpp
+++ b/libs/ipc/epoll/event-poll.cpp
@@ -87,7 +87,7 @@ void EventPoll::addFD(const int fd, const Events events, Callback&& callback)
void EventPoll::modifyFD(const int fd, const Events events)
{
- // No need to lock and check mCallbacks map
+ // No need to lock as modify doesn't touch the mCallbacks map
if (!modifyFDInternal(fd, events)) {
const std::string msg = "Could not modify fd: " + std::to_string(fd);
LOGE(msg);
diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt
index 0d35bad..e3056dc 100644
--- a/libs/lxcpp/CMakeLists.txt
+++ b/libs/lxcpp/CMakeLists.txt
@@ -51,7 +51,7 @@ TARGET_COMPILE_DEFINITIONS(${PROJECT_NAME}
PRIVATE ATTACH_PATH="${LIBEXEC_DIR}/${ATTACH_CODENAME}"
)
-ADD_DEPENDENCIES(${PROJECT_NAME} Common Logger)
+ADD_DEPENDENCIES(${PROJECT_NAME} Common Logger Config Ipc)
## Link libraries ##############################################################
FIND_PACKAGE(Boost COMPONENTS system filesystem)
@@ -59,7 +59,7 @@ PKG_CHECK_MODULES(LXCPP_DEPS REQUIRED glib-2.0)
INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIRS} ${LXCPP_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} ${Boost_LIBRARIES} Logger Config util)
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} Common ${pkgs_LDFLAGS} util ${Boost_LIBRARIES} Logger Config Ipc)
## Generate the pc file ########################################################
CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY)
diff --git a/libs/lxcpp/commands/console.cpp b/libs/lxcpp/commands/console.cpp
new file mode 100644
index 0000000..3210945
--- /dev/null
+++ b/libs/lxcpp/commands/console.cpp
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * @author Lukasz Pawelczyk (l.pawelczyk@samsung.com)
+ * @brief Implementation of the console
+ */
+
+#include "lxcpp/commands/console.hpp"
+#include "lxcpp/exception.hpp"
+#include "lxcpp/terminal.hpp"
+#include "lxcpp/credentials.hpp"
+
+#include "ipc/epoll/event-poll.hpp"
+#include "logger/logger.hpp"
+#include "utils/fd-utils.hpp"
+#include "utils/signal.hpp"
+
+#include
+#include
+#include