Cannot create more than 10 mqueues - python

I am using a python module that wraps the posix real time extensions to get MessageQueues.
This is the python code
#!/usr/bin env python
import uuid
import posix_ipc
import time
def spawn():
return posix_ipc.MessageQueue("/%s" % uuid.uuid4(), flags=posix_ipc.O_CREAT)
i = 0
while True:
i += 1
spawn()
print(i)
This will create about 10 mqs before reporting OSError: This process already has the maximum number of files open
I looked into mq limits and rlimit and checked that they are all set very high. E.g.
fs.file-max = 2097152
fs.mqueue.msg_max = 1000
fs.mqueue.queues_max = 1000
And even for privileged users it will still only create about 10 queues.
The equivalent C using the realtime extensions directly is as follows
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <mqueue.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(int argc, char **argv)
{
mqd_t mq;
struct mq_attr attr;
char buffer[1024 + 1];
int must_stop = 0;
/* initialize the queue attributes */
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 1024;
attr.mq_curmsgs = 0;
/* create the message queue */
int count = 0;
char name[5];
while (1) {
sprintf(name, "/%d", count);
mq = mq_open(name, O_CREAT | O_RDONLY, 0644, &attr);
if (mq == (mqd_t) -1)
handle_error("mq_open");
count++;
}
return 0;
}
(compile with gcc -lrt test.c)
But this only gets me 20 mqs open at one time. Realistically I want to have a few hundred maybe a thousand open at a time.
Anyone got any ideas or suggestions?
EDIT: Better error checking in the C version. Still max out.

The parameter fs.mqueue.queues_max is only a global number of message queues allowed in the system. The limit you are reaching is the number of message queues per process. Because mq_open says about error codes:
[EMFILE] Too many message queue descriptors or file descriptors
are currently in use by this process.
You should normally be able to read (an set) that per process limit with getrlimit/ setrlimit. The man page for rlimit says:
RLIMIT_MSGQUEUE (Since Linux 2.6.8)
Specifies the limit on the number of bytes that can be allocated for POSIX message queues for the real user ID of the calling process. This limit is enforced for mq_open(3). Each message queue that the user creates counts (until it is removed) against this limit according to the formula:
bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) +
attr.mq_maxmsg * attr.mq_msgsize
where attr is the mq_attr structure specified as the fourth argument to mq_open(3).
The first addend in the formula, which includes sizeof(struct msg_msg *) (4 bytes on Linux/i386), ensures that the user cannot create an unlimited number of zero-length messages (such messages nevertheless each consume some system memory for bookkeeping overhead).
You can also try to read the value and multiply it with what you need:
struct rlimit limit;
getrlimit(RLIMIT_MSGQUEUE, &limit);
limit.rlim_cur *= 20;
limit.rlim_max *= 20;
setrlimit(RLIMIT_MSGQUEUE, &limit);

Related

Arduino to Raspberry Pi Pyserial Communication not working on Python

I have a Python script that takes in input from a camera. It then gets the position of an object in the image and sends it to the Arduino via pyserial and usb with the following format.
"Xpos-XYPos-Y" demo: 90X90Y would move the servos I have connected to 90 degrees.
What should happen when i run bellow should be that it moves the motors.
import serial
ser = serial.Serial('/dev/ttyACM1', 9600, timeout=1)
ser.flush()
ser.write(bytes("90X90Y", encoding='utf-8'))
But what really happens... Nothing?
So I thought okay, it might just be that my code is wrong so I tried many different variations.
I would list them but then it would take way too long to read. Basically, I changed the encoding and how I turn it into bytes.
I know the problem isn't my hardware (or at least I think) because I can download the Arduino IDE
onto the pi and send serial info through there. And it works!
Here is my Arduino code:
#include <Servo.h>
// Define Objects
Servo X;
Servo Y;
// Create varibles
String learndata;
String receiveX;
String receiveY;
int moveX;
int moveY;
// Straight forward
int defX = 95;
int defY = 5;
void setup(){
Serial.begin(9600);
//Attatch servos
X.attach(6);
Y.attach(7);
}
void loop(){
if (Serial.available() > 0){
// Parse servo input
receiveX = Serial.readStringUntil('X');
receiveY = Serial.readStringUntil('Y');
moveX = receiveX.toInt();
moveY = receiveY.toInt();
X.write(moveX);
Y.write(moveY);
}//if (Serial.available() > 0){
}//void loop(){
I also tried fully updating the raspberry pi to no avail.
Any help and what I should do? Are there any alternatives?

Is there a Python equivalent of vfork in Unix?

I'm reading APUE.
#include "apue.h"
int globvar = 6; /* external variable in initialized data */
int main(void)
{
int var; /* automatic variable on the stack */
pid_t pid;
var = 88;
printf("before vfork\n"); /* we don′t flush stdio */
if ((pid = vfork()) < 0) {
err_sys("vfork error");
} else if (pid == 0) { /* child */
globvar++; /* modify parent′s variables */
var++;
_exit(0); /* child terminates */
}
/* parent continues here */
printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
exit()
}
It's said that vfork() creates a child process without copying the address space the parent process has. And parent will wait until child process calls exit or exec.
Is there anything similar in Python give this kind of low level control? How can this be achieved in Python if possible?
vfork is a mostly-obsolete optimization of fork, intended solely for uses where it is immediately followed by an exec. It was designed back when fork didn't use copy-on-write, and has been rendered almost entirely pointless by copy-on-write.
Your use of vfork is undefined behavior; modifying variables like globvar or var in the child is not allowed. Almost the only thing the child is allowed to do is call one of the exec* functions. The details are in the man page.
If your goal is to share memory between Python processes, you should do that with the multiprocessing module and multiprocessing.sharedctypes.
If your goal is to call vfork, go ahead and call it with ctypes, and watch your program immediately fall apart because it's impossible to call vfork safely from Python:
$ cat asdf.py
import ctypes
import os
lib = ctypes.CDLL('libc.so.6')
vfork = lib.vfork
if not vfork():
os.execv('/usr/bin/echo', ['echo', 'hello', 'world'])
print("Should print in parent, but doesn't due to memory corruption.")
$ python3.6 asdf.py
hello world
Segmentation fault (core dumped)

Difference between SCmd.readSerial() and Serial.read()

Currently I'm trying to Send information from python to Arduino through the serial port.
I manage this using only one letter Serial.read() 'P' and executing an action on my Arduino with the following code.
Arduino code:
#define arduinoLED 12 // Arduino LED on board
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
}
void loop() {
// put your main code here, to run repeatedly:
//delay (20000);
//char comein=Serial.read();
//Serial.println(comein);
char *arg = "hello";
if (Serial.read()== 'P'){
digitalWrite(arduinoLED, HIGH);
delay(5000);
}
else {
digitalWrite(arduinoLED, LOW);
Serial.println("Hello World");
}
}
Python code:
ser.open()
ser.is_open
my_string='P'
my_string_as_bytes=str.encode(my_string)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
This works well and turn my LED on but how could I manage more then one letter for the command for example 'P1 2018' for the led to turn on?
But my real problem is that I try to do exactly the same thing, using the same Python code, but using SCmd.readSerial() to read the information in Arduino such as the following:
Arduino code:
#include <SerialCommand.h>
#define arduinoLED 12 // Arduino LED on board
SerialCommand SCmd; // The demo SerialCommand object
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(arduinoLED, OUTPUT); // Configure the onboard LED for output
digitalWrite(arduinoLED, LOW); // default to LED off
SCmd.addCommand("P1", process_command1); // Converts two arguments to integers and echos them back
SCmd.addCommand("P", relay1_on); // Turns Relay1 on
SCmd.addDefaultHandler(unrecognized); // Handler for command that isn't matched (says "What?")
Serial.println("Ready");
}
void loop() {
// put your main code here, to run repeatedly:
SCmd.readSerial(); // We don't do much, just process serial commands
}
void relay1_on()
{
digitalWrite(12, HIGH);
Serial.println(3000);
delay(3000);
digitalWrite(12, LOW);
}
void process_command1()
{
int aNumber = 5;
char *arg = "hello";
Serial.println("We're in process_command");
arg = SCmd.next();
int OhmPosition = atoi(arg); //will return only numbers
arg = SCmd.next();
int relay = atoi(arg); //will return only numbers
arg = SCmd.next();
int opentime = atoi(arg); //will return only numbers
Serial.println(OhmPosition);
Serial.println(relay);
Serial.println(opentime);
}
As you can see, their is Serial command, responding to 'P' which is the same example as above but it doesn't work for some reason and don't understand why. Any idea?
And the second Serial command is 'P1' which is where I would like to get at the end, so I could send from Python something like:
Python code:
my_string6 = 'P1'+str(actions_time_[0][0] )+' '+str(actions_time_[0][1])+' '+str(actions_time_[0][2]))
my_string_as_bytes=str.encode(my_string6)
print(my_string_as_bytes)
ser.write(my_string_as_bytes)
output looks like this=> b'P1 150.0 5.0 2000.0 '
To enable me to start the P1 command and send values, to be saved in OhmPosition, Relay, Time which will be separated by a space, as the goal is to pilot a small electrical automate.
I would be very please to have your support on theses couples of point related to each other.
How can your program tell the difference between receiving the "P1" command and receiving the "P" command followed by some random "1"
You code seems to rely on a library that isn't a standard part of the Arduino install. You should provide a link to where you got the SerialCommand class.

Error in arduino communication with COM

Arduino code
#include <TFT.h>
#include <SPI.h>
#define cs 10
#define dc 9
#define rst 8
TFT TFTscreen = TFT(cs, dc, rst);
int led = 13;
void setup() {
TFTscreen.begin();
Serial.begin(9600);
pinMode(led, OUTPUT);
}
void loop() {
TFTscreen.background(0, 0, 0);
TFTscreen.setTextSize(1);
if (Serial.available() > 0) {
digitalWrite(led, HIGH);
TFTscreen.text(Serial.read(), 0, 0);
}
}
Python code
import os
import sys
import serial
import datetime
ser = serial.Serial('COM4', 9600)
print(ser.name)
print(datetime.datetime.now())
date_string = str(datetime.datetime.now())
date_bytes = date_string.encode('ascii')
ser.write(date_bytes)
print('OK')
ser.close
Python is working normal, but Arduino give me this error invalid conversion from 'int' to 'const char*' [-fpermissive], I think problem with Type of Data, but I began learn this language yesterday.
The problem is here I think:
TFTscreen.text(Serial.read(), 0, 0);
You call the "read" function which returns an integer. The "text" function of your screen wants a char pointer instead as the first parameter, and you can't cast an int to char* like said in the error "invalid conversion from 'int' to 'const char*"
You can look up all the parameter and return types in the arduino documentation:
https://www.arduino.cc/en/Serial/Read
maybe, on your python add a '\0' before sending the string to the serial, this will serve as the end of received string. I can not remember if python is sending this by default but you can explicitly just send this.
on the arduino, fetch the received data and fill a character array (maybe use a counter or do pointer aritchmetic, be careful of going past the array's declared maximum size), and then wait for the '\0'. once it gets the \0, append it as well to the char array, and do a TFT display. then repeat the process again, reset the counter then wait for the incoming byte stream.
I haven't used that TFT library but one of the problems that I anticipate in your implementation is that it will not display any words because you will keep on writing every character to 0,0.

Python C extension for a function that sleeps

I'm writing a Python extension for the functions provided by a GPIO driver. I made progress pretty easily on the simple functions like set_bit() and clear_bit(). But now I need to implement wait_int(), which sleeps until an event is sensed on an input pin and I'm not sure the right way to orchestrate this between c and python. Here's a stripped down example of using the function in c:
main(int argc, char *argv[])
{
int c;
//some setup like testing port availability, clearing interrupts, etc
...
while(1)
{
printf("**\n");
c = wait_int(1);//sleeps until an interrupt occurs on chip 1
if(c > 0) {
printf("Event sense occured on Chip 1 bit %d\n",c);
++event_count;
}
else
break;
}
printf("Event count = %05d\r",event_count);
printf("\nExiting Now\n");
}
Do I just expose wait_int pretty much directly and then do whatever the python equivalent idiom of the infinite loop is? There's also some debouncing that needs to be done. I've done it in c but maybe it could be moved to the python side.
You don't need to do anything on the Python side, you can just treat it as a synchronous function. On the C side, you just block until the event occurs, possibly allowing interrupts. For example, take a look at the implementation of the time.sleep function:
/* LICENSE: http://docs.python.org/license.html */
/* Implement floatsleep() for various platforms.
When interrupted (or when another error occurs), return -1 and
set an exception; else return 0. */
static int
floatsleep(double secs)
{
/* XXX Should test for MS_WINDOWS first! */
#if defined(HAVE_SELECT) && !defined(__BEOS__) && !defined(__EMX__)
struct timeval t;
double frac;
frac = fmod(secs, 1.0);
secs = floor(secs);
t.tv_sec = (long)secs;
t.tv_usec = (long)(frac*1000000.0);
Py_BEGIN_ALLOW_THREADS
if (select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t) != 0) {
#ifdef EINTR
if (errno != EINTR) {
#else
if (1) {
#endif
Py_BLOCK_THREADS
PyErr_SetFromErrno(PyExc_IOError);
return -1;
}
}
Py_END_ALLOW_THREADS
#elif defined(__WATCOMC__) && !defined(__QNX__)
...
All it does is use the select function to sleep for the given period of time. select is used so that if any signal is received (such as SIGINT from hitting Ctrl+C at the terminal), the system call is interrupted and control returns to Python.
Hence. your implementation can just call the C wait_int function. If it supports being interrupted by signals, than great, that will allow the user to interrupt it by hitting Ctrl+C, but make sure to react appropriately such that an exception will be thrown (I'm not certain of how this works, but it looks like returning NULL from the top-level function (time_sleep in this example) will do the trick).
Likewise, for better multithreaded performance, surround the wait call with a pair of Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS macros, but this is not required, especially if you're not using multithreading at all.

Categories