read() does not read data from pty despite they are - unix

My program is supposed to emulate external device that is usually connected via COM port (/dev/ttyUSB0). The program opens a pty and waits for commands. Here is the code:
HostPty::HostPty(const string & HostPty_name)
{
char name[100] = {0};
int res = openpty(&_master, &_slave, name, NULL, NULL);
printf("Name: %s\n", name);
}
string HostPty::nextString()
{
static const int BUF_SIZE = 4096;
char buf[BUF_SIZE];
size_t idx = 0;
while(true)
{
// Read symbols one by one until new line is found
size_t received_size = read(_master, buf + idx, 1);
printf("Received a symbol: %02x\n", buf[idx]);
// Stopping at new line
if(buf[idx] == '\n')
break;
idx++;
}
return string(buf, idx);
}
To test this code I am using miniterm.py terminal emulator connecting to /dev/pty/6 (or whatever is created with openpty) and send text commands over there.
When I type commands manually everything works fine - I receive chars one by one as expected. But when I paste a piece of multiline text this code receives only first byte until I put a new line symbol (even though there are multiple newline symbols in the text I paste).
Any ideas how to fix that?

Any ideas how to fix that?
I don't know which kind of Unix you have. I just tried to reproduce your problem under Linux; but pasting lines work fine on my computer so I cannot reproduce the problem.
If your Unix variant has a system call tracer (Linux: strace, SunOS/Solars: truss, FreeBSD: strace, MacOS: dtruss (?)), I'd trace the system calls:
strace -f -o file_myprog.out ./my_program
miniterm /dev/pty/6
(Note the -f which means that the system calls of sub-processes created by fork() are also debugged. This is necessary because Python will create such sub-processes.)
Now reproduce the situation when the program does not behave correctly and kill my_program using pkill -KILL my_program. (Send the -KILL signal to ensure that my_program is killed immediately.)
Do that again - this time debugging miniterm and killing miniterm in the "wrong situation":
./my_program
strace -f -o file_miniterm.out miniterm /dev/pty/6
At the end of the two output files (file_myprog.out and file_miniterm.out) you can see the last "actions" the two programs were doing before you killed them. There are various scenarios possible:
miniterm was sending the data to /dev/pty/6 but your program did not receive any data. In this case there is a problem with the virtual console itself.
miniterm did not send the data to /dev/pty/6 for some reason. In this case you have a problem with miniterm.
miniterm did not even receive the data pasted using read()...

Related

With Qt, how to check if stdin is empty?

I have a Qt program that processes stdin data like this:
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
QByteArray ba;
ba = stdindata.toUtf8();
QJsonDocument exJSONDoc(QJsonDocument::fromJson(ba));
QJsonObject extRoot;
extRoot = exJSONDoc.object();
QStringList keys;
keys = extRoot.keys();
for (int n=0; n <= keys.count()-1; n++)
{
qDebug() << extRoot.value(keys[n]).toString();
}
It works when I call my program like this:
myprogram < ./data.json
But if I call it without any "<" it hangs in qtin.readAll().
How can I check with Qt if the stdin is empty?
(I am assuming a Linux -or at least POSIX- operating system)
QTextStream qtin(stdin);
QString stdindata = qtin.readAll();
This would read stdin till end-of-file is reached. So works with a redirected input like
myprogram < ./data.json
But if I call it without any "<" it hangs ...
But then (that is, if you run myprogram alone) stdin is not empty. It is the same as your shell's stdin. and your program, being the foreground job, is waiting for input on the terminal you are typing (see also tty(4)). Try (in that case) typing some input on the terminal (which you could end with Ctrl D to make an end-of-file condition). Read about job control and the tty demystified and see also termios(3).
Perhaps you could detect that situation with e.g. isatty(3) on STDIN_FILENO. But that won't detect a pipe(7) like
tail -55 somefile | myprogram
You need to define what an empty stdin is for you. I have no idea what that means to you, and I would instead think of myprogram < /dev/null (see null(4)) as the way to get an empty stdin.
Perhaps you should design myprogram so that some program
option (perhaps --ignore-stdin) is avoiding any read from stdin.
Problem here is readAll. See documentation:
Reads the entire content of the stream, and returns it as a QString.
Avoid this function when working on large files, as it will consume a
significant amount of memory.
So it reads stdin until it encounters end of file and since stdin is associated with console you have to signal end of file. Usually it is Ctrl-D and press enter.
It is more probable you what to read stdin line by line.
To alow user text editing console transfers data to standard input of the application only line by line. This was designed like this ages ago when computer had only a printer as user interface (no screen).
Now question is how to read JSon form stdin console connected with console without end of file information?
I would use some SAX parser, but this would be to complicated for you.
So is there another way to detect end of JSon?
You can try this approach (this is basic idea, not final solution, so it has couple shortcomings):
QFile file(stdin);
QByteArray data = file.peak(largeNumber);
QJsonParseError error;
QJSonDocument doc = QJSonDocument::fromJson(data, &error);
while (!doc.isValid() && JSonNotTerminatedError(error.error))
{
// TODO: wait for new data - it would be best to use readyRead signal
doc = QJSonDocument::fromJson(data, &error);
}
Where JSonNotTerminatedError returns true for respective QJsonParseError::ParseError values (see linked documentation) which are related with unterminated JSon data.
Now I see QFile doesn't have required constructor, but main concept should be clear. Read data from stdin and check if it is a valid JSon document.

AutoIt Scripting for an External CLI Program - eac3to.exe

I am attempting to design a front end GUI for a CLI program by the name of eac3to.exe. The problem as I see it is that this program sends all of it's output to a cmd window. This is giving me no end of trouble because I need to get a lot of this output into a GUI window. This sounds easy enough, but I am begining to wonder whether I have found one of AutoIt's limitations?
I can use the Run() function with a windows internal command such as Dir and then get the output into a variable with the AutoIt StdoutRead() function, but I just can't get the output from an external program such as eac3to.exe - it just doesn't seem to work whatever I do! Just for testing purposesI I don't even need to get the output to a a GUI window: just printing it with ConsoleWrite() is good enough as this proves that I was able to read it into a variable. So at this stage that's all I need to do - get the text (usually about 10 lines) that has been output to a cmd window by my external CLI program into a variable. Once I can do this the rest will be a lot easier. This is what I have been trying, but it never works:
Global $iPID = Run("C:\VIDEO_EDITING\eac3to\eac3to.exe","", #SW_SHOW)
Global $ScreenOutput = StdoutRead($iPID)
ConsoleWrite($ScreenOutput & #CRLF)
After running this script all I get from the consolWrite() is a blank line - not the text data that was output as a result of running eac3to.exe (running eac3to without any arguments just lists a screen of help text relating to all the commandline options), and that's what I am trying to get into a variable so that I can put it to use later in the program.
Before I suggest a solution let me just tell you that Autoit has one
of the best help files out there. Use it.
You are missing $STDOUT_CHILD = Provide a handle to the child's STDOUT stream.
Also, you can't just do RUN and immediately call stdoutRead. At what point did you give the app some time to do anything and actually print something back to the console?
You need to either use ProcessWaitClose and read the stream then or, you should read the stream in a loop. Simplest check would be to set a sleep between RUN and READ and see what happens.
#include <AutoItConstants.au3>
Global $iPID = Run("C:\VIDEO_EDITING\eac3to\eac3to.exe","", #SW_SHOW, $STDOUT_CHILD)
; Wait until the process has closed using the PID returned by Run.
ProcessWaitClose($iPID)
; Read the Stdout stream of the PID returned by Run. This can also be done in a while loop. Look at the example for StderrRead.
; If the proccess doesnt end when finished you need to put this inside of a loop.
Local $ScreenOutput = StdoutRead($iPID)
ConsoleWrite($ScreenOutput & #CRLF)

Terminating a process specially in QEMU

Example code:
int main () {
printf("Hello world begin\n");
// New instruction
__asm__ __volatile__ (".byte 0x0f\n\t"
".byte 0xd0\n\t"
:);
printf("Hello world end\n");
return 0;
}
My problem [TLDR] :
Make QEMU treat my new instruction similar to return 0; [sys_exit]
My purpose:
I am trying to customize the QEMU emulation of x86 ISA to log some data (like number of ring transitions etc) during CPU emulation between two points. Assume for simplicity, the start will be after the first printf (or some syscall) and end will be marked by a new instruction that I have written (say opcode '0f d0' which is unused in Intel ISA) whose purpose is to simply print those log information and terminate the process there (in line 2) and without executing the rest of the lines. In other words, the behavior should be identical to a scenario where 'return 0;' was placed right after my new instruction.
In my QEMU helper logic, I tried to add cpu_loop_exit() and all other combinations, they seem to loop infinitely. Can anyone point me how to achieve the behavior I want (with only modifying QEMU and not my example code) ?

Iterating through !DumpHeap output to read value at memory offset

I'm trying to come up with a WinDbg command line expression that takes the output of the !DumpHeap command and for each address, reads a 64-bit value from offset 0x08 after the address. I think this is possible (not sure about it) but every attempt I made so far fails with some error.
I searched a lot but most WinDbg articles show simple examples which I can try but my attempts fail.
I have a process dump of an ASP.NET worker process. The process has some memory growth but there's no clear offender so I'm trying to list a number of objects that appear many times in memory. I'm using sos.dll for the managed debugging WinDbg extensions.
Here's what I'm trying to do
.foreach(myaddress {!dumpheap -short -mt 000007fe998adea8})
{r #$t0=poi(myaddress+0x8);!do #$t0;.echo ************* myaddress}
Note, that the above command must be on a single line - I only added a line break for better readability here.
For the above line, WinDbg prints this error: Couldn't resolve error at 'myaddress+0x8);!do #$t0;.echo ************* 00000001003cb870'.
I'm trying to iterate through all addresses returned by !DumpHeap - each address should go into the myaddress variable. Then, for each address, I'm trying to set the $t0 user register to the value read from myaddress+0x8. The !do (!DumpObject) command would then dump the object at that address.
If I run only (again, on one line in WinDbg):
.foreach(myaddress {!dumpheap -short -mt 000007fe998adea8})
{!do myaddress;.echo ************* myaddress}
I get a list of object dumps but this is one level higher than what I need. I want to drill down one level deeper and dump a particular member of these top-level objects that I'm iterating through.
Is this possible or am I on the wrong track with this?
After further searching, I found that I was using the wrong syntax. According to question and to MSDN, variable names must be surrounded by spaces or must be enclosed in ${...} to work. After I used the ${} enclosure, my script started working.
For future reference, here's how to run the script (keep it on one line in WinDbg):
.foreach(myaddress {!dumpheap -short -mt 000007fe998adea8})
{r #$t0=poi(${myaddress}+0x8);!do #$t0;.echo ************* myaddress}
yes you need space around the aliases
.foreach ( place { .shell -ci "!DumpHeap -stat" sed 1,3d | awk "{print
$1 }" } ) { .foreach (plays { !DumpHeap -short -mt place } ) { r $t0 =
poi( plays + 8 ) ; !do #$t0 ; .echo
========================================= } }

Arduino Serial Output Dropping Characters

I have a bizarre one here with the serial output when trying to write some code for my Arduino Uno.
I have this proto-code:
MyClass myclass;
void setup()
{
Serial.Begin(9600);
Serial.println("Starting...");
}
void loop()
{
int status = myclass.DoWork();
Serial.println("Status: " + status);
}
class MyClass
{
int DoWork()
{
Serial.println("Doing some work...");
return 1;
}
}
Now when this runs I get the following output:
Starting...
Doing some work...
atus: 1
So the strange part is the "Status: 1" missing the first few characters. Is this because I am using serial in an object improperly or something?
I have noticed when I reference another library that also uses serial like MyClass does that I get other strange output behavior... so I assume that I am doing something wrong.
EDIT: In the end this turned out to actually be a memory issue. A library I was including was quite large and it was consuming the available memory. I found this by adding a few more debugging statements and found the corruption shifted around based on the string lengths and positions. By using the F() function I moved the strings to flash memory (e.g. I now run Serial.println(F("Starting...")); and it has corrected the strange output.
You cannot add strings and integers in C++. It would have been better for you if this failed to compile:
Serial.println("Status: " + status);
Instead the compiler guessed at something. It guessed wrong. Use this:
Serial.print("Status :");
Serial.println(status);
or for complete control of outputting numbers and strings learn to use C string formatting, sprintf()
In the end this turned out to actually be a memory issue. A library I was including was quite large and it was consuming the available memory. I found this by adding a few more debugging statements and found the corruption shifted around based on the string lengths and positions. By using the F() function I moved the strings to flash memory (e.g. I now run Serial.println(F("Starting...")); and it has corrected the strange output.
One more possible explanation.
I was running minicom to monitor, and I usually like that it auto-reconnects after resetting my device.
Well I minimized a terminal running minicom last night, and today I started a new instance that somehow also got connected to the same serial port (if that is even possible).
I think the two instances of minicom were each reading ~50% of the serial characters roughly at random, leaving me with quite a mess of text.

Resources