I am new to uvlib. Is it normal to call uv_run twice if one wants to avoid blocking inside function? If not, then which instruments are available, except threads? Here I just open and close file.
#include <uv.h>
#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#ifdef _WIN32
#include <conio.h>
#include <Windows.h>
#define Sleep(x) Sleep(x)
#else
#include <unistd.h>
#define Sleep(x) sleep(x)
#endif
uv_loop_t* loop;
uv_fs_t open_req;
uv_fs_t close_req;
void open_cb(uv_fs_t*);
void close_cb(uv_fs_t*);
const char *filename = "C:/c/somedata.txt";
int main(int argc, char **argv) {
int r;
loop = uv_loop_new();
r = uv_fs_open(loop, &open_req, filename, O_RDONLY, S_IREAD, open_cb);
if (r < 0) {
printf("Error at opening file: %s\n", uv_strerror(r));
}
printf("in main now\n");
uv_run(loop, UV_RUN_DEFAULT);
uv_loop_close(loop);
return 0;
}
void open_cb(uv_fs_t* req) {
int result = req->result;
if (result < 0) {
printf("Error at opening file: %s\n", uv_strerror(result));
} else {
printf("Successfully opened file.\n");
}
uv_fs_req_cleanup(req);
uv_fs_close(loop, &close_req, result, close_cb);
uv_run(loop, UV_RUN_DEFAULT);
Sleep(5000);
printf("ok now\n");
}
void close_cb(uv_fs_t* req) {
int result = req->result;
printf("in close_cb now\n");
if (result < 0) {
printf("Error at closing file: %s\n", uv_strerror(result));
} else {
printf("Successfully closed file.\n");
}
}
Set aside your example, libuv offers the opportunity to run the loop more than once.
See the documentation for further details.
In particular, uv_run function accepts a parameter of type uv_run_mode.
Possible values are:
UV_RUN_DEFAULT: it doesn't stop unless you explicitly stop it and until there exists at least on referenced or active resource on the loop.
UV_RUN_ONCE: poll for I/O once and execute all the functions that are ready to be served. It has the drawback that it is blocking if there are no pending callbacks.
UV_RUN_NOWAIT: this is probably the one you are looking for, similar to the previous one, but it doesn't block if there are no pending callbacks.
Note that with both UV_RUN_ONCE and UV_RUN_NOWAIT you'll have to run the loop more than once.
Return value usually indicates if there are some other pending callbacks. In this case, the loop must be run sooner or later in the future.
The last mode, UV_RUN_NOWAIT, is probably the one you are looking for.
As an example, it can be used in scenarios where the client has its own loop and cannot block on the libuv's one.
Is it normal to run the loop more than once?
Well, yes, but it mostly depends on your actual problem if it's right.
It's hard to say from a 100 line snippet on SO.
Related
static void timeDelay(int no_of_seconds)
{
#ifdef _WIN32
Sleep(1000 * no_of_seconds);
#else
sleep(no_of_seconds);
#endif
}
void somefunction(){
printf("\t\t Load ... \n\t\t");
fflush(stdout);
for (int i = 1; i <= 60; i++)
{
fflush(stdout);
timeDelay(1);
if (i == 31)
printf("\n\t\t");
printf("*****");
}
}
I have included the header files too:
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
The stars are printed instantaneously.
I added fflush(stdout) after seeing the answers here. I also commented out the if (i==31) {} portion to check if that's causing the problem but it isn't. So what is wrong with my code?
According to the sleep() manpage...
NOTES
On Linux, sleep() is implemented via nanosleep(2). See the nanosleep(2) man page for a discussion of the
clock used.
So I have rewritten your program to use nanosleep. As you are working with WSL, I've dropped any reference to Win32, only Linux. Well, the thing is that this program exits nanosleep() prematurely, with an "Invalid argument" error. I cannot see why is that.
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
void timeDelay (time_t no_of_seconds)
{
struct timespec req, rem;
int res;
req.tv_sec = no_of_seconds;
req.tv_nsec = 0;
do
{
rem.tv_sec = 0;
rem.tv_nsec = 0;
res = nanosleep (&req, &rem);
req = rem;
}
while (res == EINTR);
if (res)
perror("nanosleep");
}
void somefunction()
{
printf("\t\t Load ... \n\t\t");
fflush(stdout);
for (int i = 1; i <= 60; i++)
{
fflush(stdout);
timeDelay(1);
putchar('*');
}
}
int main()
{
somefunction();
return 0;
}
I've also tried with NULL instead of rem, and reissuing nanosleep() with the original time instead of the remaining time, and putting the test and the perror() within the loop to print all possible errors from nanosleep. No matter what I do, I always receive an EINVAL from the first call to nanosleep()
So, there seems to be a real problema with nanosleep() on WSL. See https://github.com/microsoft/WSL/issues/4898 . It mentions a problem for WSL being unable to read the realtime clock from a certain version of glibc. I tried this in my WSL terminal:
$ sleep 1
sleep: cannot read realtime clock: Invalid argument
There is a mention of a workaround here:
https://github.com/microsoft/WSL/issues/4898#issuecomment-612622828
I've tried with another approach: using clock_nanosleep() so I can choose another source for the clock: in the above program, just change the call to nanosleep() with this other to clock_nanosleep()
clock_nanosleep (CLOCK_MONOTONIC, 0, &req, &rem);
There is no problem with CLOCK_MONOTONIC, and now the program works!
I'm using a library for my project. This library sometimes prints some messages to stdout. This is a problem for me because the messages are mixed up along with the application messages. It will be useful to a stop this behaviour or have them printed to a different window. I'm using C Language and Mingw32 enviroment. How can I do this? Thanks.
You might be able to (nonportably) swap the stdout with another stream:
#include <stdio.h>
FILE *devnull;
#define SWAPSTDOUT() do{ FILE *tmp = stdout; stdout = devnull; devnull = tmp; }while(0)
int main(void)
{
/*program initialization*/
if(0==(devnull= fopen("/dev/null", "r"))) return 1;
fputs("your code 0\n",stdout);
SWAPSTDOUT();
fputs("library code 0\n",stdout); //should be silent
SWAPSTDOUT();
fputs("your code 1\n", stdout);
}
Unfortunately, that's unlikely to work with functions that hardcode stdout (e.g., printf or puts).
If you're on a POSIX platform, you might have freopen but that won't help much if you can't save the original stream. However, on POSIX you could fflush(stdout) and then shuffle the underlying file descriptors, which should be quite reliable:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
int devnull, tmp;
int swapstdout(void);
int main(void)
{
/*program initialization*/
if(0>(devnull=open("/dev/null", O_RDONLY))) return EXIT_FAILURE;
if(0>(tmp=dup(devnull))) return EXIT_FAILURE; //reserve a fd spot
fputs("your code 0\n",stdout);
if(0>swapstdout()) return EXIT_FAILURE:
fputs("library code 0\n",stdout); //should be silent
if(0>swapstdout()) return EXIT_FAILURE:
fputs("your code 1\n", stdout);
}
int swapstdout(void)
{
if(0>fflush(stdout)) return -1;
if(0>dup2(STDOUT_FILENO,tmp)) return -1; /*really shouldn't happen*/
if(0>dup2(devnull,STDOUT_FILENO)) return -1; /*really shouldn't happen*/
if(0>tmp=dup(devnull)) return -1; /*really shouldn't happen unless we're multithreaded and another thread steals the fd spot*/
}
Either solution depends on your code being single threaded.
In any case, well behaved library functions should leave files they don't own alone, unless you explicitly request them to do something with such files.
My problem is to deal with sparse file reads and understand where the extents of the file are to perform some logic around it.
Since, there is no direct API call to figure these stuff out, I decided to use ioctl api to do this. I got the idea from how cp command deals with problems of copying over sparse files by going through their code and ended up seeing this.
https://github.com/coreutils/coreutils/blob/df88fce71651afb2c3456967a142db0ae4bf9906/src/extent-scan.c#L112
So, I tried to do the same thing in my sample program running in user space and it errors out with "Invalid argument". I am not sure what I am missing or if this is even possible from userspace. I am running on ubuntu 14.04 on an ext4 file system. Could this be a problem with device driver supporting these request modes underneath?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include "fiemap.h" //This is from https://github.com/coreutils/coreutils/blob/df88fce71651afb2c3456967a142db0ae4bf9906/src/fiemap.h
int main(int argc, char* argv[]) {
int input_fd;
if(argc != 2){
printf ("Usage: ioctl file1");
return 1;
}
/* Create input file descriptor */
input_fd = open (argv [1], O_RDWR);
if (input_fd < 0) {
perror ("open");
return 2;
}
union { struct fiemap f; char c[4096]; } fiemap_buf;
struct fiemap *fiemap = &fiemap_buf.f;
int s = ioctl(input_fd, FS_IOC_FIEMAP, fiemap);
if (s == 0) {
printf("ioctl success\n");
} else {
printf("ioctl failure\n");
char * errmsg = strerror(errno);
printf("error: %d %s\n", errno, errmsg);
}
/* Close file descriptors */
close (input_fd);
return s;
}
As you're not properly setting the fiemap_buf.f parameters before invoking ioctl(), it is likely that the EINVAL is coming from the fiemap invalid contents than from the FS_IOC_FIEMAP request identifier support itself.
For instance, the ioctl_fiemap() (from kernel) will evaluate the fiemap.fm_extent_count in order to determine if it is greater than FIEMAP_MAX_EXTENTS and return -EINVAL in that case. Since no memory reset nor parameterization is being performed on fiemap, this is very likely the root cause of the problem.
Note that from the coreutils code you referenced, it performs the correct parameterization of fiemap before calling ioctl():
fiemap->fm_start = scan->scan_start;
fiemap->fm_flags = scan->fm_flags;
fiemap->fm_extent_count = count;
fiemap->fm_length = FIEMAP_MAX_OFFSET - scan->scan_start;
Note fiemap is not recommended as you have to be sure to pass FIEMAP_FLAG_SYNC which has side effects. The lseek(), SEEK_DATA and SEEK_HOLE interface is the recommended one, though note that will, depending on file system, represent unwritten extents (allocated zeros) as holes.
I am working on what I believe should be a simple program I have googled around and all I can find is stuff for C#, C++.
What I would like to accomplish is to start my program written in C and have it listen for certain keystrokes. I have a function written that will move a servo so I would like to integrate the Up and Down arrow keys to execute the function to move the servo one direction or the other. Is this possible in C?
Are you working on linux or windows? Based on that, there are alternatives that can be used.
If you are working on windows, a function should be familiar to you : kbhit()? Though it is now deprecated, the working knowledge of it could be useful :)
Assuming that you are working on linux, have you tried NCurses?
Taken from [Here]: (http://www.linuxmisc.com/9-unix-programmer/d5b30f8d1faf8d82.htm)
The problem is three-fold:
You have to check if data is available without blocking. A simple
'read' or fgets' or whatever will block your process until data is
available -- you don't want that.
You have to bypass any buffering
because otherwise you would have to check both the buffer and the
device.
You need to coerce the terminal driver to give you data as
it's available rather than accumulating the whole thing into a
line.
From the same page:
That said, I present the following awkward, hastily-written,
uncommented code, which may be instructive or may not ( edited in part by me, was missing parenthesis and not indented)
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
static struct termios orig_term;
void u_cleanup(void)
{
tcsetattr(0, TCSANOW, &orig_term);
}
int u_kbhit(void)
{
struct termios t;
int ret;
fd_set rfd;
struct timeval to;
static int first_hit=0;
if(first_hit==0)
{
if(tcgetattr(0, &t)!=0) exit(0);
orig_term=t;
cfmakeraw(&t);
if(tcsetattr(0, TCSANOW, &t)!=0) exit(0);
atexit(u_cleanup);
first_hit=1;
}
FD_ZERO(&rfd);
FD_SET(0, &rfd);
to.tv_sec=0;
to.tv_usec=0;
if(select(1, &rfd, NULL, NULL, &to)==1) return 1;
return 0;
}
int u_getchar(void)
{
int ret;
fd_set rfc;
unsigned char buf;
if(read(0, &buf, 1)!=1) ret=0;
else ret=buf;
return ret;
}
int main(void)
{
while(1)
{
if(u_kbhit())
{
int key=u_getchar();
printf("hit: %d\r\n", key);
if(key==3)
{
printf("you hit control-c\r\n");
exit(0);
}
}
usleep(100);
}
return 0; // inaccessible code, to prevent compiler warning
}
I am trying to read data from a bluetooth barcode scanner (KDC300) using C. Here is the code I have so far, and the program successfully establishes a bluetooth connection to the scanner, but when a barcode is scanned, no input is displayed on the screen (Eventually more will be done with the data, but we have to get it working first, right).
Here is the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
int main (int argc, const char * argv[]) {
// define vars
int STOP = 0;
//char buf[255];
if(argv[1])
{
int fd = open("/dev/tty.KDC1", O_RDONLY);
if(fd == -1)
{
printf("%s", strcat("Unable to open /dev/tty.", argv[1]));
}
int res;
while(STOP == 0)
{
while((res = read(fd,buf,255)) == 0);
{
if(res > 0)
{
buf[res]=0;
printf("%s:%d\n", buf, res);
if(buf[sizeof(buf)]=='\n') break;
}
}
}
}
return 0;
}
If anyone has any ideas, I am at a loss on this so far. If it is any help, I can run screen /dev/tty.KDC1 and any barcodes scanned on the scanner appear in the terminal, I just can't do anything with the data.
Jud
This line:
while((res = read(fd,buf,255)) == 0);
Does not do what you think it does. That's a while loop with an empty body.
#tommieb75,
the strcat statement was from the first "go" at the program, I took a variable from argv[1] and appended it to the /dev/tty.* so you could select which device you wanted to monitor.
I am not sure why I had commented out buf, probably stems from looking at the code too much / trying different approaches and forgetting where I was (not much of a C programmer, which is how I can get lost in 30 LOC).
#caf, Good catch on the extra semi-colon after the while loop, unfortunately, even after correcting it, the program doesn't behave correctly.
I am researching the problem further. I can verify (with osx packetlogger) that the computer is getting the data, but the but the buffer never has any data placed in it.
-Jud
---------------Edit--------------
I solved the problem after a little trial and error. Adding the following code to setup the serial connection solved everything:
struct termios theTermios;
memset(&theTermios, 0, sizeof(struct termios));
cfmakeraw(&theTermios);
cfsetspeed(&theTermios, 115200);
theTermios.c_cflag = CREAD | CLOCAL; // turn on READ
theTermios.c_cflag |= CS8;
theTermios.c_cc[VMIN] = 0;
theTermios.c_cc[VTIME] = 10; // 1 sec timeout
ioctl(fileDescriptor, TIOCSETA, &theTermios);
Thanks to the other answers for getting me to this point.
Here is the best info I've found.
The C program on there using termios worked just by adding
#include<string.h>
And changing the baudrate to match my needs.
In your code
printf("%s", strcat("Unable to open /dev/tty.", argv[1]));
Why did you do that? It would be easier to do it this way:
printf("%s: Unable to open /dev/tty.KDC1", argv[0]);
Why the parameter referencing to the command line?
res = read(fd,buf,255)
Why did you have buf declaration commented out above?