Using open and i2c in C++ - c++

I've realized that open() and ioctl() does not work inside a cpp object. I am able to do the operation if it is called inside my main() function, but NOT when inside any of my classes. I have a object that is running in my main loop that has another object that makes the file system calls.
So basically when in the main loop it can open (I get a 3 for the pointer and the ioctl is successful). But when I do it in object it returns 0 for open (which isn't supposedly an error) and the ioctl fails.
I know I can't use the ios:: iostream options because they don't work with ioctl. How can I make regular ioctl work inside a cpp object?
int add=0x4b;
int i2c_bus;
if(( i2c_bus = open( "/dev/i2c-0", O_RDWR )) < 0 )
{
printf("Unable to open file /dev/i2c-0.\n");
}
if( ioctl( i2c_bus, I2C_SLAVE, add ) < 0 )
{
printf("Open chip %d FAILED file %d\n",add, i2c_bus);
return -1;
}
else
{
printf("Open chip %d Succeeded file %d\n\n",add, i2c_bus);
return 1;
}

You've assigned the result of open to i2c_bus, but you're using fd in the ioctl. Did you change the variable names when you moved from main?

Related

Cygwin - Blocking on opening a named fifo causes another thread to block on opening a regular file

A blocked open of a named pipe in Cygwin causes another thread to hang when it tries to open any file, including a simple text file. The below code reproduces the issue on cygwin 3.1.6(0.340/5/3), and works fine (does not hang) on RHEL 7.
#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <thread>
#include <sys/stat.h>
#include <fcntl.h>
void openFile() {
int fd;
printf("inside new thread\n");
sleep(10); // Ensure main thread reaches call to open()
printf("opening a simple file\n");
if((fd = open("simpleFile", 0600)) == -1) { // simpleFile is a simple text file in the filesystem
printf("failed opening a simple file\n");
}
printf("simple file opened successfully\n");
close(fd);
printf("simple file closed\n");
}
int main(int argc, char *argv[]) {
int fd;
char readBuffer[PIPE_BUF];
printf("creating named pipe\n");
if (mkfifo("namedPipe", 0600)) {
printf("creating named pipe failed\n");
}
printf("creating thread\n");
std::thread pipeCreator = std::thread(openFile);
printf("opening named pipe for read\n");
fd = open("namedPipe", O_RDONLY); // Block will only release when we echo something into namedPipe
printf("reading from named pipe\n");
if (read(fd, readBuffer, PIPE_BUF) == -1) {
printf("error reading from pipe\n");
}
printf("read successfully from named pipe\n");
pipeCreator.join();
return 0;
}
Running this prints:
creating named pipe
creating thread
opening named pipe for read
inside new thread
opening a simple file
And then blocks until the other side of the namedPipe is opened.
Once freed it writes the rest of the prints:
reading from named pipe
simple file opened successfully
read successfully from named pipe
simple file closed
On RHEL this prints the expected result:
creating named pipe
creating thread
opening named pipe for read
inside new thread
opening a simple file
simple file opened successfully
simple file closed
And only then the main thread hangs until something is echoed into namedPipe.
We're working on a workaround which won't block, but that involves busy waiting which isn't great.
Can anyone explain this behavior?
On Cygwin the open syscall locks the file descriptor table for the entire duration of the syscall. Which means all open syscalls are essentially sequentialized.
See syscalls.cc/open():
extern "C" int
open (const char *unix_path, int flags, ...)
{
. . .
cygheap_fdnew fd; // <-- here
And cygheap.h:
class cygheap_fdnew : public cygheap_fdmanip
{
public:
cygheap_fdnew (int seed_fd = -1, bool lockit = true)
{
if (lockit)
cygheap->fdtab.lock (); // <-- here
. . .
I see no easy way around this, but I guess it should be possible to unlock the fd table once a descriptor has been created at least in case of a fifo (see fhandler_fifo), since a fifo blocks on open. You can discuss this further on cygwin-developers.

Communication with Arduino using Linux

This is the first time I'm communicating with Arduino using my computer. I use Ubuntu 14.04. This is the C program for writing to the file. The Arduino shows up ttyACM0.
While compiling using gcc the compiler shows an error saying:
Segmentation fault(core dumped)
How do I rectify this error.
#include<unistd.h>
#include<stdio.h>
int main() {
char data[] = {'f','b','r'}; //Random data we want to send
FILE *file;
file = fopen("/dev/ttyACM0","w"); //Opening device file
int i = 0;
for(i = 0 ; i < 3 ; i++) {
fprintf(file,"%c",data[i]); //Writing to the file
fprintf(file,"%c",','); //To separate digits
sleep(1);
}
fclose(file);
}
Pardon my ignorance. I tried researching on it. Couldn't make it work. Thanks in advance for your help.
You're getting a NULL return from the fopen() that NULL is being passed to fprintf() which is expecting a valid FILE* and messing up causing the SEGV.
If you use fopen you should check what it returns so you can give the user a something more useful than "segmentation fault".
The probable cause of the fopen() failure is you don't have permission to play with the serial port.
Normally you need the group dialout to be able to access the serial port.
As root do:
usermod -a -G dialoutyourusername
Then log out and back in so you get the new group.
Consider using minicom or microcom (on any of the several other serial terminal programs) to access the serial port instead of writing your own.
I also suggest you have the Arduino send a hello message when it boots up so you can be sure you have the right baud rate etc...
You did not put any success check on the return value of fopen("/dev/ttyACM0","w");. In case fopen() fails, using file further is undefined behavior, causing segmentation fault. Do something like
file = fopen("/dev/ttyACM0","w"); //Opening device file
if (file)
{
//do something with file
}
else
return 0;
Also, add a return 0 before ending main().
// the following code:
// compiles cleanly
// performs appropriate error checking
// has proper return statement
#include <unistd.h> // sleep()
#include <stdio.h> // fopen(), fclose(), fprintf(), perror()
#include <stdlib.h> // exit() and EXIT_FAILURE
int main()
{
char data[] = {'f','b','r'}; //Random data we want to send
FILE *file;
if( NULL == (file = fopen("/dev/ttyACM0","w") ) ) //Opening device file
{ // then fopen failed
perror("fopen failed for ttyACM0" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
int i = 0;
for(i = 0 ; i < 3 ; i++)
{
if( 0 >= fprintf(file,"%c",data[i]) ) //Writing to the file
{ // fprintf failed
perror("fprintf data failed" );
exit( EXIT_FAILURE );
}
// implied else, fprintf successful for data
if( 0 >= fprintf(file,"%c",',') ) //To separate digits
{ // then, fprintf failed
perror( "fprintf for comma failed");
exit( EXIT_FAILURE );
}
// implied else, fprintf successful for comma
sleep(1);
} // end for
fclose(file);
return(0);
} // end function: main
On failure fopen returns NULL, so you are potentially dereferencing a NULL pointer, the correct way of doing that, is checking the result of fopen. I would however suggest low level IO for this kind of thing something like
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main()
{
char data[] = {'f','b','r'}; //Random data we want to send
int fd;
int i;
fd = open("/dev/ttyACM0", O_WRONLY); //Opening device file
if (fd == -1)
{
perror("cannot open /dev/ttyACM0");
return -1;
}
for(i = 0 ; i < 3 ; i++)
{
write(fd, &(data[i]), 1);
write(fd, ",", 1);
sleep(1);
}
close(fd);
return 0;
}
on error open returns a special value -1 so you should abort writing to it.
I'm pretty sure in your case there will be a permission denied error, since normally the /dev/tty* belong to group dialout and they have group write permission by default, but since probably your user doesn't belong to that group you don't have write access to /dev/ttyACM0.

SIGSTOP signal everytime i run my program for named pipe in linux c++

I have a program for checking if pipe exist or not so wrote this in a function :
status = mkfifo("recv",0666);
fd1 = open("recv",O_WRONLY);
fd2 = open("sendd", O_RDONLY);
cout<<"we are checking botth bcz we have both read and write in the program------:)";
if(fd1 <0 && fd2 <0)
{
//strerror(errno);
err = 1;// a const for remote
}
else if(fd1 >0 || fd2 >0){
err = 2; // a const for local
}
else{
err = 3; // a const for progrm failure error
cout<<"program has some problems";
}
But everytime i run my program it stops at fd1 = open("recv",O_WRONLY); saying Thread1: signal SIGSTOP although it works correctly with just fd2= open("sendd", O_RDONLY); I dont know why its giving this error?? i am new to pipes in linux.
RTFM, http://linux.die.net/man/3/mkfifo
Once you have created a FIFO special file in this way, any process can open it for reading or writing, in the same way as an ordinary file. However, it has to be open at both ends simultaneously before you can proceed to do any input or output operations on it. Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa.

Creating text file into C++ addon of node.js

I want to know how i can create file and append data inside it in c++ addon (.cc) file of node.js ??
I have used below code to do same, but not able to find file "data.txt" in my ubuntu machine(reason behind it may be below code is not correct way to create file, but strange i haven't received any error/warning at compile time).
FILE * pFileTXT;
pFileTXT = fopen ("data.txt","a+");
const char * c = localReq->strResponse.c_str();
fprintf(pFileTXT,c);
fclose (pFileTXT);
Node.js relies on libuv, a C library to handle the I/O (asynchronous or not). This allows you to use the event loop.
You'd be interested in this free online book/introduction to libuv: http://nikhilm.github.com/uvbook/index.html
Specifically, there is a chapter dedicated to reading/writing files.
int main(int argc, char **argv) {
// Open the file in write-only and execute the "on_open" callback when it's ready
uv_fs_open(uv_default_loop(), &open_req, argv[1], O_WRONLY, 0, on_open);
// Run the event loop.
uv_run(uv_default_loop());
return 0;
}
// on_open callback called when the file is opened
void on_open(uv_fs_t *req) {
if (req->result != -1) {
// Specify the on_write callback "on_write" as last argument
uv_fs_write(uv_default_loop(), &write_req, 1, buffer, req->result, -1, on_write);
}
else {
fprintf(stderr, "error opening file: %d\n", req->errorno);
}
// Don't forget to cleanup
uv_fs_req_cleanup(req);
}
void on_write(uv_fs_t *req) {
uv_fs_req_cleanup(req);
if (req->result < 0) {
fprintf(stderr, "Write error: %s\n", uv_strerror(uv_last_error(uv_default_loop())));
}
else {
// Close the handle once you're done with it
uv_fs_close(uv_default_loop(), &close_req, open_req.result, NULL);
}
}
Spend some time reading the book if you want to write C++ for node.js. It's worth it.

How to read the failure log message displayed when a system call failed in C++?

I have a C++ code that calls a test. I am doing a system call to execute this test. When this test fails, it will display something like this " ERROR: One or more devices of following component type(s) could not be discovered:"
I have a C++ code that runs on Linux redhat and it is capable of detecting if the system call pass or failed. But it can not capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:) and append into the log file or print it.
Can someone please tell me how to capture the error message (ERROR: One or more devices of following component type(s) could not be discovered:)?
PS: I am an intern, any help would be really nice.
#include<iostream.h>
int main ()
{
int i;
if (system(NULL))
puts ("Ok");
else
exit (1);
i=system("hpsp --discover -verbose --user Admin --oapasswd password");
printf ("The value returned was: %d.\n",i);
return false;
}
Instead of using system() use popen(). This will open a pipe capturing the standard output of the test program so that your program can read it via the pipe.
Example EDITED:
#define _BSD_SOURCE 1
#define BUFFSIZE 400
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *cmd = "hpsp --discover -verbose --user Admin --oapasswd password";
char buf[BUFFSIZE];
char* searchResult;
int testPassed = 0;
FILE *ptr;
if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFFSIZE, ptr) != NULL)
{
if ((searchResult = strstr(buf, "The test passed")) != NULL )
{
testPassed = 1;
break;
}
}
if (testPassed)
printf("yea!!\n");
else
printf("boo!!\n");
pclose(ptr);
return 0;
}
You can use dup and dup2 to backup/store the stderr file descriptor to redirect to your log file. Well, I'm guessing that errors go to stderr anyways.
Here's an example if you just want to write to a log file.
//open log file, choose whatever flags you need
int logfd = open("whateveryourlogfileis", O_APPEND);
//back up stderr file descriptor
int stderr_copy = dup(STDERR_FILENO);
//redirect stderr to your opened log file
dup2(logfd, STDERR_FILENO);
//close the original file descriptor for the log file
close(logfd);
//system call here
//restore stderr
dup2(stderr_copy, STDERR_FILENO);
//close stderr copy
close(stderr_copy);
Note: dup2 closes the target file descriptor before dup2ing to it. dup just duplicates the file descriptor and returns to you the new file descriptor.