if ( !list.empty() )
{
+ // A data race when reload changes max_size while other threads read this may
+ // delay pruning by one round. Yet, we are avoiding mutex for better performance.
max_size = current_size;
if ( max_size > new_size )
{
int ControlConn::shell_execute(int& current_fd, Request*& current_request)
{
- if ( !request->read(fd) )
+ if ( !request->read() )
return -1;
current_fd = fd;
#include "utils/util.h"
using namespace snort;
+using namespace std;
//-------------------------------------------------------------------------
// request foo
//-------------------------------------------------------------------------
-bool Request::read(const int& f)
+bool Request::read()
{
bool newline_found = false;
char buf;
ssize_t n = 0;
- fd = f;
while ( (bytes_read < sizeof(read_buf)) and ((n = ::read(fd, &buf, 1)) > 0) )
{
read_buf[bytes_read++] = buf;
if ( queue_response )
{
- queued_response = s;
+ lock_guard<mutex> lock(queued_response_mutex);
+ queued_response.emplace(s);
return;
}
write_response(s);
}
#ifdef SHELL
-void Request::send_queued_response()
+bool Request::send_queued_response()
{
- if ( queued_response )
+ const char* qr;
{
- write_response(queued_response);
- queued_response = nullptr;
+ lock_guard<mutex> lock(queued_response_mutex);
+ if ( queued_response.empty() )
+ return false;
+ qr = queued_response.front();
+ queued_response.pop();
}
+ return write_response(qr);
}
#endif
#ifndef REQUEST_H
#define REQUEST_H
+#include <mutex>
+#include <queue>
+
#include "main/snort_types.h"
class Request
{
public:
- Request(int f = -1) : fd(f), bytes_read(0), queued_response(nullptr) { }
+ Request(int f = -1) : fd(f), bytes_read(0) { }
- bool read(const int&);
+ bool read();
const char* get() { return read_buf; }
bool write_response(const char* s) const;
void respond(const char* s, bool queue_response = false, bool remote_only = false);
#ifdef SHELL
- void send_queued_response();
+ bool send_queued_response();
#endif
private:
int fd;
char read_buf[1024];
size_t bytes_read;
- const char* queued_response;
+ std::queue<const char*> queued_response;
+ std::mutex queued_response_mutex;
};
#endif
#include "config.h"
#endif
+#include <unistd.h>
+
#include "main/request.h"
#include <CppUTest/CommandLineTestRunner.h>
{};
//--------------------------------------------------------------------------
-// Make sure request->read does not modify value of passed-in fd
+// Make sure multiple responses are queued
//--------------------------------------------------------------------------
-TEST(request_tests, request_read_fail_test)
+TEST(request_tests, queued_response_test)
{
- const int fd_orig_val = 10;
- int current_fd = fd_orig_val;
-
- Request *request = new Request(current_fd);
-
- CHECK(request->read(current_fd) == false);
- CHECK(current_fd == fd_orig_val);
+ Request request(STDOUT_FILENO);
- delete request;
+ CHECK(request.send_queued_response() == false); // empty queue
+ request.respond("reloading", true);
+ request.respond("swapping", true);
+ CHECK(request.send_queued_response() == true);
+ CHECK(request.send_queued_response() == true);
+ CHECK(request.send_queued_response() == false); // empty queue after being written
}
//-------------------------------------------------------------------------
desired_cpuset = iter->second->cpuset;
else
desired_cpuset = process_cpuset;
+
+ // A data race in this library function ensues from the usage of a static variable
+ // to dump chars when calculating string length. This does not affect functionality.
hwloc_bitmap_list_asprintf(&s, desired_cpuset);
current_cpuset = hwloc_bitmap_alloc();