I would like to control various ov5640 camera parameters by using ioctl and VIDIOC_S_CTRL from V4L2 in the following manner:
#include <string>
#include <iostream>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <cstring>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#define IOCTL_TRIES 3
#define CLEAR(x) memset (&(x), 0, sizeof (x))
static int xioctl(int fd, int request, void *arg)
{
int r;
int tries = IOCTL_TRIES;
do {
r = ioctl(fd, request, arg);
} while (--tries > 0 && r == -1 && EINTR == errno);
return r;
}
bool v4l2_ctrl_set(int fd, uint32_t id, int val)
{
struct v4l2_control ctrl;
CLEAR(ctrl);
ctrl.id = id;
ctrl.value = val;
if (xioctl(fd, VIDIOC_S_CTRL, &ctrl) == -1) {
std::cout << "Failed to set ctrl with id "
<< id << " to value " << val
<< "\nerror (" << errno << "): " << strerror(errno) << std::endl;
return false;
}
return true;
}
int main()
{
int fd = open("/dev/video0", O_RDWR | O_NONBLOCK);
if (fd == -1) {
std::cout << "Failed to open the camera" << std::endl;
return -1;
}
v4l2_ctrl_set(fd, V4L2_CID_SATURATION, 100);
return 0;
}
Unfortunately ioctl fails and I get error (25): Inappropriate ioctl for device. I'm using Intrinsyc Open-Q 820 µSOM with linaro 4.14. I've managed to add some debugs prints to ov5640 driver file in ov5640_s_ctrl function before if (sensor->power_count == 0) { (in case there were problems with power save mode) and recompile the kernel. I ran the code, but looking through dmesg my printk message doesn't get printed, so that means that ov5640_s_ctrl doesn't get called even though the callback is set:
static const struct v4l2_ctrl_ops ov5640_ctrl_ops = {
.g_volatile_ctrl = ov5640_g_volatile_ctrl,
.s_ctrl = ov5640_s_ctrl,
};
Am I using V4L2 wrong? Should I enable something before setting the controls? It's even more confusing since I manage to get an image from the camera with v4l2, but I can't set/get any controls.
In the the kernel source code of ov5640.c that you supplied, the driver is assigned the flag V4L2_SUBDEV_FL_HAS_DEVNODE which means it might supply a subdev node /dev/v4l-subdevX. According to the kernel docs:
Device nodes named v4l-subdevX can be created in /dev to access sub-devices directly. If a sub-device supports direct userspace configuration it must set the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.`
So you can try to set the control directly from the v4l-subdevX node if it exists.
Related
I have a multi threaded program on Raspberry in which I want to handle SIGTERM and shut everything down gracefully. The issue is that I have a background thread that has called recvfrom() on a blocking socket. As per my understanding from the man pages, if I exit my handler all the system calls should be woken up and return with -1 and errno set to EINTR. However in my case the recvfrom call keeps hanging.
1) In general am I understanding this right, that all threads that have blocking system calls that are able to be woken up by a signal should wake up in this scenario?
2) Could it be that the operating system is setting some special signal mask on my thead?
The interresting part is that I am using the VideoCore primitives, not pthread, maybe that could be the cause? Here is a small test example:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include "interface/vcos/vcos.h"
void SignalHandler(int nSignalNumber)
{
std::cout << "received signal " << nSignalNumber << std::endl;
}
void* ThreadMain(void* pArgument)
{
int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (nSocket >= 0)
{
sockaddr_in LocalAddress;
memset(&LocalAddress, 0, sizeof(LocalAddress));
LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = INADDR_ANY;
LocalAddress.sin_port = htons(1234);
if (bind(nSocket, reinterpret_cast<sockaddr *>(&LocalAddress), sizeof(LocalAddress)) == 0)
{
sockaddr_in SenderAddress;
socklen_t nSenderAddressSize = sizeof(SenderAddress);
unsigned char pBuffer[512];
std::cout << "calling recvfrom()" << std::endl;
int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast<struct sockaddr *>(&SenderAddress), &nSenderAddressSize);
if (nBytesReceived == -1)
{
if (errno == EINTR)
{
std::cout << "recvfrom() was interrupred by a signal" << std::endl;
}
else
{
std::cout << "recvfrom() failed with " << errno << std::endl;
}
}
}
else
{
std::cout << "bind() failed with " << errno << std::endl;
}
close(nSocket);
}
else
{
std::cout << "socket() failed with " << errno << std::endl;
}
return NULL;
}
int main(int argc, char** argv)
{
struct sigaction SignalAction;
memset(&SignalAction, 0, sizeof(SignalAction));
SignalAction.sa_handler = SignalHandler;
sigaction(SIGTERM, &SignalAction, NULL);
VCOS_THREAD_T Thread;
VCOS_STATUS_T nVcosStatus = vcos_thread_create(&Thread, "", NULL, ThreadMain, NULL);
if (nVcosStatus == VCOS_SUCCESS)
{
void* pData = NULL;
vcos_thread_join(&Thread, &pData);
}
else
{
std::cout << "vcos_thread_create() failed with " << nVcosStatus << std::endl;
}
return EXIT_SUCCESS;
}
It can be compiled like this:
g++ test.cpp -I/opt/vc/include -L/opt/vc/lib -lvcos -o test
When I run it and then call kill on the running instance the output is:
calling recvfrom()
received signal 15
and the process hangs. I'll try if a pthread behaves differently.
UPDATE
Ok I updated the sample to spawn a pthread thread as well and that one is not quitting as well. So I assume the signals are not populated to all threads?
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include "interface/vcos/vcos.h"
void SignalHandler(int nSignalNumber)
{
std::cout << "received signal " << nSignalNumber << std::endl;
}
void* ThreadMain(void* pArgument)
{
const char* pThreadType = reinterpret_cast<const char*>(pArgument);
int nSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (nSocket >= 0)
{
sockaddr_in LocalAddress;
memset(&LocalAddress, 0, sizeof(LocalAddress));
LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = INADDR_ANY;
LocalAddress.sin_port = htons(pThreadType[0] * 100);
if (bind(nSocket, reinterpret_cast<sockaddr *>(&LocalAddress), sizeof(LocalAddress)) == 0)
{
sockaddr_in SenderAddress;
socklen_t nSenderAddressSize = sizeof(SenderAddress);
unsigned char pBuffer[512];
std::cout << "calling recvfrom()" << std::endl;
int nBytesReceived = recvfrom(nSocket, pBuffer, sizeof(pBuffer), 0, reinterpret_cast<struct sockaddr *>(&SenderAddress), &nSenderAddressSize);
if (nBytesReceived == -1)
{
if (errno == EINTR)
{
std::cout << "recvfrom() was interrupred by a signal" << std::endl;
}
else
{
std::cout << "recvfrom() failed with " << errno << std::endl;
}
}
}
else
{
std::cout << "bind() failed with " << errno << std::endl;
}
close(nSocket);
}
else
{
std::cout << "socket() failed with " << errno << std::endl;
}
std::cout << pThreadType << " thread is exiting" << std::endl;
return NULL;
}
int main(int argc, char** argv)
{
struct sigaction SignalAction;
memset(&SignalAction, 0, sizeof(SignalAction));
SignalAction.sa_handler = SignalHandler;
sigaction(SIGTERM, &SignalAction, NULL);
VCOS_THREAD_T VcosThread;
VCOS_STATUS_T nVcosStatus = vcos_thread_create(&VcosThread, "", NULL, ThreadMain, const_cast<char*>("vcos"));
bool bJoinVcosThread = false;
if (nVcosStatus == VCOS_SUCCESS)
{
bJoinVcosThread = true;
}
else
{
std::cout << "vcos_thread_create() failed with " << nVcosStatus << std::endl;
}
pthread_t PthreadThread;
int nPthreadStatus = pthread_create(&PthreadThread, NULL, ThreadMain, const_cast<char*>("pthread"));
bool bJoinPthreadThread = false;
if (nPthreadStatus == 0)
{
bJoinPthreadThread = true;
}
else
{
std::cout << "pthread_create() failed with " << nPthreadStatus << std::endl;
}
if (bJoinVcosThread)
{
void* pData = NULL;
vcos_thread_join(&VcosThread, &pData);
}
if (bJoinPthreadThread)
{
void* pData = NULL;
pthread_join(PthreadThread, &pData);
}
return EXIT_SUCCESS;
}
A signal such as SIGTERM is submitted to one thread in the process only. The only precondition is that the chosen thread must either have not masked the signal, or must wait for it using sigwait. The other threads will not be directly notified that the signal has been delivered.
A common approach to combine signals with threads is to have a separate thread which handles signals only and notifies the other threads using thread synchronization mechanisms such as condition variables.
For interrupting file I/O, this may not be sufficient because there is a race condition between checking for a termination request and making the system call to perform the I/O operation. Some language run-time libraries use non-blocking I/O with poll or epoll with a special file descriptor which becomes ready on signal delivery (either using the previously-mentioned thread-based approach, or something Linux-specific like signalfd). Others try to avoid this overhead by using the read and write system calls directly with a complicated dance which uses dup2 to replace the file descriptor with one that always causes I/O to fail, thereby avoiding the race condition (but the bookkeeping needed for that is fairly complicated).
The manpage for signal reads:
If a signal handler is invoked while a system call or library function call is blocked, then either:
the call is automatically restarted after the signal handler returns; or
the call fails with the error EINTR.
Which of these two behaviors occurs depends on the interface and whether or not the signal handler was established using the SA_RESTART flag (see sigaction(2)). The details vary across UNIX systems<...>
A few lines below, recvfrom is listed among the functions that use SA_RESTART behavior by default. (Note: this behavior is disabled if there's a timeout on the socket, though.)
Thus, you should fill the sa_flags field of the sigaction structure to carefully avoid setting the SA_RESTART flag.
A good way to deal with blocking sockets -see socket(7)- (and even non blocking ones) is to use a multiplexing syscall like poll(2) (or the obsolete select(2)....)
Regarding signals, be sure to read signal(7) and signal-safety(7).
A common way to handle signals with some event loop (using poll(2)) is to have a signal handler which simply write(2)-s a byte on a pipe(7) to self (you'll setup the pipe at initialization, and you'll poll it in your event loop). The Qt documentation explains how and why. You might also use the Linux specific signalfd(2).
I'm trying to port a program from Windows to Linux.
I encountered a problem when I found out that there isn't a "real" ReadProcessMemory counterpart on Linux; I searched for an alternative and I found ptrace, a powerful process debugger.
I quickly coded two small console applications in C++ to test ptrace, before using it in the program.
TestApp
This is the tracee; it keeps printing two integers every 50 milliseconds while increasing their value by 1 every time.
#include <QCoreApplication>
#include <QThread>
#include <iostream>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int value = 145;
int i = 0;
do {
cout << "i: " << i << " " << "Value: " << value << endl;
value++;
i++;
Sleeper::msleep(50);
} while (true);
return a.exec();
}
MemoryTest
This is the tracer; it asks for the process name and retrieves the PID using the command pidof -s, then ptrace attaches to the process and retrieves the memory address' value every 500 milliseconds, for 10 times.
#include <QCoreApplication>
#include <QThread>
#include <iostream>
#include <string>
#include <sys/ptrace.h>
#include <errno.h>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char process_name[50];
cout << "Process name: ";
cin >> process_name;
char command[sizeof(process_name) + sizeof("pidof -s ")];
snprintf(command, sizeof(command), "pidof -s %s", process_name);
FILE* shell = popen(command, "r");
char pidI[sizeof(shell)];
fgets(pidI, sizeof(pidI), shell);
pclose(shell);
pid_t pid = atoi(pidI);
cout << "The PID is " << pid << endl;
long status = ptrace(PTRACE_ATTACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
unsigned long addr = 0x012345; // Example address, not the true one
int i = 0;
do {
status = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
i++;
Sleeper::msleep(500);
} while (i < 10);
status = ptrace(PTRACE_DETACH, pid, NULL, NULL);
cout << "Status: " << status << endl;
cout << "Error: " << errno << endl;
return a.exec();
}
Everything works fine, but TestApp is paused (SIGSTOP) until ptrace detaches from it.
Also, when it attaches to the process, the status is 0 and the error is 2; the first time it tries to retrieve the memory address value it fails with status -1 and error 3. Is it normal?
Is there a way to prevent ptrace from sending the SIGSTOP signal to the process?
I already tried using PTRACE_SEIZE instead of PTRACE_ATTACH, but it doesn't work: status -1 and error 3.
Update: Using Sleeper in MemoryTest before the "do-while" loop fixes the problem of the first memory address value retrieval, even if the value of seconds, milliseconds or microseconds is 0. Why?
After a lot of research I'm pretty sure that there isn't a way to use ptrace without stopping the process.
I found a real ReadProcessMemory counterpart, called process_vm_readv, which is much more simple.
I'm posting the code in the hope of helping someone who is in my (previous) situation.
Many thanks to mkrautz for his help coding MemoryTest with this beautiful function.
#include <QCoreApplication>
#include <QThread>
#include <sys/uio.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <iostream>
using namespace std;
class Sleeper : public QThread
{
public:
static void usleep(unsigned long usecs){QThread::usleep(usecs);}
static void msleep(unsigned long msecs){QThread::msleep(msecs);}
static void sleep(unsigned long secs){QThread::sleep(secs);}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
char process_name[50];
cout << "Process name: ";
cin >> process_name;
char command[sizeof(process_name) + sizeof("pidof -s ")];
snprintf(command, sizeof(command), "pidof -s %s", process_name);
FILE* shell = popen(command, "r");
char pidI[sizeof(shell)];
fgets(pidI, sizeof(pidI), shell);
pclose(shell);
pid_t pid = atoi(pidI);
cout << "The PID is " << pid << endl;
if (pid == 0)
return false;
struct iovec in;
in.iov_base = (void *) 0x012345; // Example address, not the true one
in.iov_len = 4;
uint32_t foo;
struct iovec out;
out.iov_base = &foo;
out.iov_len = sizeof(foo);
do {
ssize_t nread = process_vm_readv(pid, &out, 1, &in, 1, 0);
if (nread == -1) {
fprintf(stderr, "error: %s", strerror(errno));
} else if (nread != in.iov_len) {
fprintf(stderr, "error: short read of %li bytes", (ssize_t)nread);
}
cout << foo << endl;
Sleeper::msleep(500);
} while (true);
return a.exec();
}
Davide,
Have you had a look at the /proc filesystem? It contains memory map files that can be used to peek at the full process space. You can also write in the space to set a breakpoint. There is a wealth of other information in /proc as well.
The PTRACE_CONT command can be used to continue a process. Generally, the target will be paused with a PTRACE_ATTACH when the debugger attaches.
The man page says PTRACE_SIEZE should not pause the process. What flavor and version of Linux are you using? PTRACE_SIEZE has been around for quite awhile so I'm not sure why you are having trouble there.
I note the addr value is set to 0x12345. Is this a valid address in the target space? Or was that just an example? How is the stack address of interest (&value) communicated between the two processes?
I'm not too sure about the return codes. Generally a 0 means all is well, the errno may just be a hangover value from the last error.
--Matt
The following code works just fine when linking with Oracle client 11g but if I compile the same linking with Oracle 12c libraries I receive the error EINVAL Invalid argument - errno 22.
#include <sys/types.h>
#include <aio.h>
#include <fcntl.h>
#include <errno.h>
#include <iostream>
using namespace std;
const int SIZE_TO_READ = 100;
int main()
{
// open the file
int file = open("blah.txt", O_RDONLY, 0);
if (file == -1)
{
cout << "Unable to open file!" << endl;
return 1;
}
// create the buffer
char* buffer = new char[SIZE_TO_READ];
// create the control block structure
aiocb cb;
memset(&cb, 0, sizeof(aiocb));
cb.aio_nbytes = SIZE_TO_READ;
cb.aio_fildes = file;
cb.aio_offset = 0;
cb.aio_buf = buffer;
// read!
if (aio_read(&cb) == -1)
{
cout << "Unable to create request!" << endl;
close(file);
}
cout << "Request enqueued!" << endl;
// wait until the request has finished
while(aio_error(&cb) == EINPROGRESS)
{
cout << "Working..." << endl;
}
// success?
int numBytes = aio_return(&cb);
if (numBytes != -1)
cout << "Success!" << endl;
else
cout << "Error!" << endl;
// now clean up
delete[] buffer;
close(file);
return 0;
}
Then to compile I first set the env variables
export ICLIBHOME=/u01/oracle/product/Linux/2.6/x86_64/clients/12.1.0.2/64bit/client/lib
export LD_LIBRARY_PATH=${ICLIBHOME}
Afterwards I compile and execute my compiled file but I get the error
g++ myaio.cpp -o myaio -lrt -L${ICLIBHOME} -lclntsh
./myaio
Unable to create request 22
I have this simple program where I am trying to protect a block of memory, and then read a file into that memory, releasing it when it segfaults..
first I thought there was only a problem if the file is a fifo.. but now it seems that even for a normal file it fails,
this is the code:
#include <errno.h>
#include <string.h>
#include <iostream>
#include <assert.h>
#include <malloc.h>
#include <sys/mman.h>
#include <unistd.h>
#include <map>
#include <algorithm>
#include <unistd.h>
#include <signal.h>
using namespace std;
#define BUFFER_SIZE 8000
#define handle_error(msg) \
do { cout << __LINE__ << endl ;perror(msg); exit(EXIT_FAILURE); } while (0)
volatile int fault_count = 0;
char* buffer = 0;
int size = 40960;
int my_fault_handler(void* addr, int serious) {
if (mprotect(buffer, size,
PROT_READ | PROT_WRITE) == -1)
handle_error("mprotect");
++fault_count;
cout << "Segfaulting" << endl;
return 1;
}
static void handler(int sig, siginfo_t *si, void *unused) {
my_fault_handler(si ->si_addr, sig);
}
int main (int argc, char *argv[])
{
long pagesize = sysconf(_SC_PAGESIZE);
struct sigaction sa;
sa.sa_flags = SA_SIGINFO | SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = &handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1)
perror("sigaction");
cerr << "pageSize: " << pagesize << endl;
buffer = (char*)memalign(pagesize, size);
if (buffer == NULL)
handle_error("memalign");
if (mprotect(buffer, size, PROT_READ) == -1)
handle_error("mprotect");
FILE* file = fopen("test", "r");
cout << "File Open" << endl;
if (!file) {
cout << "Failed opening file " << strerror(errno) << endl;
return 0;
}
//*buffer = 0;
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
cout << ' ' << strerror(errno) << endl;
return(0);
}
note the //*buffer = 0;, if I unmark this line the program segfaults and works correctly..
anyone has any idea?
the errno is bad address.
Thanks!
UPDATE:
It seems a similiar question was asked here:
Loading MachineCode From File Into Memory and Executing in C -- mprotect Failing
where posix_memalign was suggested, I have tried this and it didn't work.
The problem is that you're not checking for an error in the FILE handle after a short read.
What the system would tell you is that the first fread failed and didn't trigger the fault handler.
If you checked for ferror outside the loop (sloppy as an example):
while(fread(buffer, pagesize*2, 1, file)) {
if (mprotect(buffer, size,
PROT_READ) == -1)
handle_error("mprotect");
}
if (ferror(file) != 0) {
cout << "Error" << endl;
}
Why it failed is that the underlying read failed, and returned an errno of 14 (EFAULT), which is not quite what is documented to happen when read fails in this situation (it says that Buf points outside the allocated address space.)
You can only trust the signal handler to be triggered in the mprotect case when the code in question is running in the user context, most system calls will fail and return EFAULT in the case that the buffer is invalid or does not have the correct permissions.
I'm trying to send a 1KB string over a message queue between a parent process and its forked child. Unfortunately, my calls to msgsnd, msgrcv, etc. are suddenly all returning -1 and causing the EINVAL error.
I found that this error (in the case of msgsnd, for example) occurs when msqid is invalid, the message type argument is set at <1, or the msgsz is out of range. But upon testing, as far as I can tell, msgget is returning a perfectly valid ID number and the type is set fine. There must be a problem with my buffer ranges, but I thought I set them up correctly. In the code, I have added comments to explain (sorry about all of the frantically-added #includes):
#include <errno.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <cstring>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <sstream>
#define PERMS (S_IRUSR | S_IWUSR)
#define NUMBYTES 1024 //number of chars (bytes) to be sent
using namespace std;
//Special structure for messages
typedef struct {
long mtype;
char mtext[NUMBYTES];
} mymsg_t;
int main(){
//Construct a generic test message of the specified size
char message[NUMBYTES];
for(int i = 0; i < NUMBYTES; i++)
message[i] = 'a';
//Create the message queue (accessed by both parent
//and child processes)
int msqid;
int len;
if(msqid = msgget(IPC_PRIVATE, PERMS) == -1)
perror("Failed to create new message queue!\n");
if(fork() == 0){ //Child process...does the sending
mymsg_t* mbuf;
len = sizeof(mymsg_t) + strlen(message); //doesn't work with " + sizeof(message)" either
void* space;
if((space = malloc(len)) == NULL) //this works fine; no error output
perror("Failed to allocate buffer for message queue.\n");
mbuf = (mymsg_t*)space;
strcpy(mbuf->mtext, message);
mbuf->mtype = 1; //a default
//Some error checks I tried...
//cout<<"msqid is " << msqid << endl;
//cout << "mbuf ptr size is " << sizeof(mbuf) << ". And this non-ptr: "<<sizeof(*mbuf)<<". And
//len: "<<len<<endl;
if(msgsnd(msqid, mbuf, len+1, 0) == -1)
perror("Failed to send message.\n"); //this error occurs every time!
free(mbuf);
}
else{ //Parent process...does the receiving
usleep(10000); //Let the message come
mymsg_t mymsg; //buffer to hold message
int size;
if((size = msgrcv(msqid, &mymsg, len+1, 0, 0)) == -1) //error every time
perror("Failed to read message queue.\n");
//checking that it made it
//cout << "Hopefully printing it now? : " << endl;
//if(write(STDOUT_FILENO, mymsg.mtext, size) == -1)
// perror("Failed to write to standard output!\n");
}
ostringstream oss;
oss << "ipcrm -q " << msqid;
string command = oss.str();
if(system(command.c_str()) != 0) //also errors every time, but not main focus here
perror("Failed to clean up message queue!");
}
What is going on here? I thought I had the buffer procedure working fine and with sufficient space..