C keep track of aio_read task - c

I have a function that starts an aio_read task and returns to the main program.
I want to periodically check if the task is completed to close the file descriptor and maybe notify the user.
My current approach is declaring a struct that contains the struct aiocb of the task and the file descriptor. Adding it to a global array and checking if any task is working with the following (aio_check function):
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <aio.h>
#include <unistd.h>
#include "aioqueue.h"
void aio_add(struct aiocb a, int fd) {
for (int i = 0; i < MAX; i++) {
if (aio_array[i].valid == 0) {
aio_pack tmp;
tmp.cb = a;
tmp.fd = fd;
tmp.valid = 1;
aio_array[i] = tmp;
printf("request enqueued\n");
return;
}
}
printf("This shell cannot keep track of so many IO operations :/ \n");
}
void aio_check() {
for (int i = 0; i < MAX; i++) {
// wait until the request has finished
if(aio_array[i].valid) {
if (aio_error(&aio_array[i].cb) != EINPROGRESS) {
int nleidos = aio_return(&aio_array[i].cb);
if (nleidos != -1)
printf("AIO Task finished: %d B\n", nleidos);
else
printf("Error!");
close(aio_array[i].fd);
aio_array[i].valid = 0;
} else {
printf("At least one AIO task is in progress\n");
}
}
}
}
and the code for aioqueue.h
#define MAX 10
typedef struct {
struct aiocb cb;
int fd;
int valid;
} aio_pack;
aio_pack aio_array[MAX];
void aio_add(struct aiocb a, int fd);
void aio_check();
The problem is that if i call aio_check after i added a task i always get the
At least one AIO task is in progress
message. Even if it's clear that the task has finished.
I suppose that it might be due to the fact that im passing a copy of the struct aiocb in a moment where the aio_error is EINPROGRESS and as its a copy it never gets updated. But im pretty lost at this moment. Any help would be greatly appreciated.
Thank you in advance.

You need to call aio_suspend() in order to process what i/o's have completed, otherwise aio_error() etc will never return differently. See https://github.com/ned14/llfio/blob/master/include/llfio/v2.0/detail/impl/posix/io_service.ipp#L290.

Related

Printf with multiple threads (for real-time logging) in C

I have written a code for real-time logging. Here's the pseudo-code:
initialize Q; //buffer structure stores values to be printed
log(input)
{
push input to Q;
}
printLog() //infinte loop
{
loop(1)
{
if(Q is not empty)
{
values = pop(Q);
msg = string(values); //formating values into a message string
print(msg);
}
}
}
mainFunction()
{
loop(1)
{
/*
insert operations to be performed
*/
log(values); //log function called
}
}
main()
{
Create 4 threads; //1 mainFunction and 3 printLog
Bind them to CPUs;
}
I'm using atomic operations instead of locks.
When I print the output to the console, I see that each thread prints consecutively for a while. This must mean that once a thread enters printLog(), the other threads are inactive for a while.
What I want instead is while one thread is printing, another thread formats the next value popped from Q and prints it right after. How can this be achieved?
EDIT: I've realized the above information isn't sufficient. Here are some other details.
Buffer structure Q is a circular array of fixed size.
Pushing information to Q is faster than popping+printing. So by the time the Buffer structure is full, I want most of the information to be printed.
NOTE: mainFunction thread shouldn't wait to fill Buffer when it is full.
I'm trying to utilize all the threads at a given time. Currently, after one thread prints, the same thread reads and prints the next value (this means the other 2 threads are inactive).
Here's the actual code:
//use gcc main.c -o run -pthread
#define _GNU_SOURCE
#include <unistd.h>
#include <stdint.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <signal.h>
#include <stdlib.h>
#define N 3
/* Buffer size */
#define BUFFER_SIZE 1000
struct values
{
uint64_t num;
char msg[20];
};
struct values Q[BUFFER_SIZE];
int readID = -1;
int writeID = -1;
int currCount = 0;
void Log(uint64_t n, char* m)
{
int i;
if (__sync_fetch_and_add(&currCount,1) < BUFFER_SIZE)
{
i = __sync_fetch_and_add(&writeID,1);
i = i%BUFFER_SIZE;
Q[i].num = n;
strcpy(Q[i].msg, m);
}
else __sync_fetch_and_add(&currCount,-1);
}
void *printLog(void *x)
{
int thID = *((int*)(x));
int i;
while(1)
{
if(__sync_fetch_and_add(&currCount,-1)>=0)
{
i = __sync_fetch_and_add(&readID,1);
i = i%BUFFER_SIZE;
printf("ThreadID: %2d, count: %10d, message: %15s\n",thID,Q[i].num,Q[i].msg);
}
else __sync_fetch_and_add(&currCount,1);
}
}
void *mainFunction()
{
uint64_t i = 0;
while(1)
{
Log(i,"Custom Message");
i++;
usleep(50);
}
}
int main()
{
/* Set main() Thread CPU */
cpu_set_t cpusetMain;
CPU_ZERO(&cpusetMain);
CPU_SET(0, &cpusetMain);
if(0 != pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpusetMain))
printf("pthread_setaffinity_np failed for CPU: 0\n");
int LogThID[N+1];
pthread_t LogThreads[N+1];
/* Create Threads */
if (pthread_create(&LogThreads[0], NULL, &mainFunction, NULL) != 0){return 0;}
for(int i=1; i<N+1 ; i++)
{
LogThID[i] = i;
if (pthread_create(&LogThreads[i], NULL, &printLog, &LogThID[i]) != 0){return i;}
}
/* Set CPUs */
cpu_set_t cpuset[N+1];
for(int i=0; i<N+1; i++)
{
CPU_ZERO(&cpuset[i]);
CPU_SET(i+1, &cpuset[i]);
if(0 != pthread_setaffinity_np(LogThreads[i], sizeof(cpu_set_t), &cpuset[i]))
printf("pthread_setaffinity_np failed for CPU: %d\n", i+1);
}
struct sched_param param[N+1];
for(int i=0; i<N+1; i++)
{
param[i].sched_priority = 91;
if(0 != pthread_setschedparam(LogThreads[i],SCHED_FIFO,&param[i]))
printf("pthread_setschedparam failed for CPU: %d\n", i);
}
/* Join threads */
for(int i=0; i<N+1; i++)
{
pthread_join(LogThreads[i], NULL);
}
return 0;
}

AIO Asynchronous I/O with a callback function -- looking for best way

I'm trying to learn POSIX asynchronous I/O. Below is an edit I have made to someone else's illustration code. I am trying to understand a few things.
First, I have a busy-wait loop near the end that keys off of the int read_complete. Is that an "acceptable" (safe, whatever, ....) alternative to keying off of the return value of aio_error()? Also, I was thinking as an alternative to the busy-wait loop, there would be a way to put the main thread to sleep and have the callback function send some kind of signal that would wake it up. But I can't figure out how to do that, if it can be done.
Finally, I'm trying to figure out how to get more info into the callback function i_am_done. For instance, let's say I wanted to shove the input data into a buffer, or split it up between buffers, that the main thread could use later, and the buffers might be different with each call if I had multiple reads to do. How could I let i_am_done know what the buffers are?
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <aio.h>
//#include <bits/stdc++.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
const int BUFSIZE = 1024;
int read_complete = 0;
void i_am_done(sigval_t sigval)
{
struct aiocb *req;
req = (struct aiocb *)sigval.sival_ptr; //Pay attention here.
/*Check again if the asynchrony is complete?*/
if (aio_error(req) == 0)
{
read_complete = 1;
}
close(req->aio_fildes);
}
int main(void)
{
struct aiocb my_aiocb;
struct timeval t0, t1;
int fd = open("file.txt", O_RDONLY);
if (fd < 0)
perror("open");
bzero((char *)&my_aiocb, sizeof(my_aiocb));
my_aiocb.aio_buf = malloc(BUFSIZE);
if (!my_aiocb.aio_buf)
perror("my_aiocb.aio_buf");
my_aiocb.aio_fildes = fd;
my_aiocb.aio_nbytes = BUFSIZE;
my_aiocb.aio_offset = 0;
//Fill in callback information
/*
Using SIGEV_THREAD to request a thread callback function as a notification method
*/
my_aiocb.aio_sigevent.sigev_notify = SIGEV_THREAD;
my_aiocb.aio_sigevent.sigev_notify_function = i_am_done;
my_aiocb.aio_sigevent.sigev_notify_attributes = NULL;
my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
int ret = aio_read(&my_aiocb);
if (ret < 0)
perror("aio_read");
//The calling process continues to execute
while (read_complete != 1) {}
printf("main thread %s\n", (char*)my_aiocb.aio_buf);
return 0;
}
Answering question #2, simply define a data structure into which you store the additional data you need, and set sival_ptr to that. For example:
struct my_data {
struct aiocb cb;
// For demonstration's sake:
int foo;
char *bar;
size_t quux;
}
// ...
struct my_data data;
data.cb.aio_sigevent.sigev_value.sival_ptr = &data;
// Setup the rest of the struct and execute the read.
In the callback, you have access to the my_data struct now.

How to continue running a process after completing threads?

I got stuck when I was trying to print the summary of all threads (namely, grand totals of a group of threads).
The C code below runs 10 threads, simulating agents that sell tickets. After running & completing the threads (i.e. after all the tickets are sold), I want to print the list of agents and corresponding number of tickets sold by that agent. However, the main process terminates as soon as it hits the line pthread_exit(NULL) (marked with a preceding comment) and the code does not return to main, where it is supposed to print the grand totals (this block is marked with a comment as well).
Can anyone tell what's wrong with the code?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
struct ThreadArgs {
int thNum;
int *numTickets;
int *soldTickets;
sem_t *lock;
};
void *SellTickets(void *th) {
struct ThreadArgs *thArgs;
int sleepTime;
thArgs = th;
while (1) {
sleepTime = rand();
if (sleepTime % 2) {
usleep(sleepTime % 1000000);
}
sem_wait(thArgs->lock);
if (*thArgs->numTickets == 0) {
break;
}
printf("There are %3d ticket(s). Agent %d sold a ticket.\n", *thArgs->numTickets, thArgs->thNum);
(*thArgs->numTickets)--;
sem_post(thArgs->lock);
(*thArgs->soldTickets)++;
}
sem_post(thArgs->lock);
pthread_exit(NULL);
}
void runThreads(int numAgents, int numTickets, int soldTickets[]) {
struct ThreadArgs thArgs[numAgents];
int agent;
pthread_t th[numAgents];
sem_t lock;
sem_init(&lock, 1, 1);
for (agent = 0; agent < numAgents; agent++) {
thArgs[agent].thNum = agent;
thArgs[agent].soldTickets = &soldTickets[agent];
thArgs[agent].numTickets = &numTickets;
thArgs[agent].lock = &lock;
pthread_create(&th[agent], NULL, SellTickets, &thArgs[agent]);
}
// when debugging, the process terminates here
pthread_exit(NULL);
}
int main() {
int agent, numAgents, numTickets, soldTickets[10];
numAgents = 10;
numTickets = 150;
for (agent = 0; agent < numAgents; agent++) {
soldTickets[agent] = 0;
}
runThreads(numAgents, numTickets, soldTickets);
// the process never executes the following block
for (agent = 0; agent < numAgents; agent++) {
printf("Agent %d sold %d ticket(s).\n", agent, soldTickets[agent]);
}
return 0;
}
pthread_exit() exits a thread, even the "main"-thread.
If main() ends all other thread go down as well.
As the "main"-thread is expected to do some final logging, it should wait until all threads spawned have ended.
To accomplish this in runThreads() replace the call to
pthread_exit(NULL);
by a loop calling pthread_join() for all PThread-IDs as returned by pthread_create().
Also you want to add error checking to all pthread*() calls, as you should do for every function call returning any relevant info, like for example indicating failure of the call.

Repeating timerfd event works with epoll and not with poll

I am implementing a timer using timerfd. This is a relative timer that I just need to repeat forever at the rate it is set to. I want to poll on this event and originally tried using poll. When I did this, I would see the timer event the first time and then never again. However, when I changed to using epoll (no change at all to how the timerfd was set up) it works as expected.
Here is the code with poll:
#include <sys/timerfd.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
int main(int ac, char *av[])
{
struct pollfd p;
int timerfd;
struct itimerspec timerValue;
/* clear pollfd */
bzero(&p, sizeof(p));
/* set timerfd */
timerfd = timerfd_create(CLOCK_REALTIME, 0);
if (timerfd < 0) {
printf("failed to create timer fd\n");
exit(1);
}
bzero(&timerValue, sizeof(timerValue));
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
/* set events */
p.fd = timerfd;
p.revents = 0;
p.events = POLLIN;
/* start timer */
if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) {
printf("could not start timer\n");
exit(1);
}
/* wait for events */
while (1) {
int numEvents = poll(&p, 1, -1);
if (numEvents > 0) {
int timersElapsed = 0;
(void) read(p.fd, &timersElapsed, 8);
printf("timers elapsed: %d\n", timersElapsed);
}
}
exit(0);
}
And here is the code with epoll:
#include <sys/timerfd.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
int main(int ac, char *av[])
{
struct epoll_event epollEvent;
struct epoll_event newEvents;
int timerfd;
int epollfd;
struct itimerspec timerValue;
/* set timerfd */
timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
if (timerfd < 0) {
printf("failed to create timer fd\n");
exit(1);
}
bzero(&timerValue, sizeof(timerValue));
timerValue.it_value.tv_sec = 1;
timerValue.it_value.tv_nsec = 0;
timerValue.it_interval.tv_sec = 1;
timerValue.it_interval.tv_nsec = 0;
/* set events */
epollfd = epoll_create1(0);
epollEvent.events = EPOLLIN;
epollEvent.data.fd = timerfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, timerfd, &epollEvent);
/* start timer */
if (timerfd_settime(timerfd, 0, &timerValue, NULL) < 0) {
printf("could not start timer\n");
exit(1);
}
/* wait for events */
while (1) {
int numEvents = epoll_wait(epollfd, &newEvents, 1, 0);
if (numEvents > 0) {
int timersElapsed = 0;
(void) read(epollEvent.data.fd, &timersElapsed, 8);
printf("timers elapsed: %d\n", timersElapsed);
}
}
exit(0);
}
Any idea what I might be doing wrong with poll? Maybe it is not meant to be used this way with a timerfd? Thank you.
Ok, this is an old question, but nevertheless. The problem lies in these lines of code:
int timersElapsed = 0;
(void) read(p.fd, &timersElapsed, 8);
printf("timers elapsed: %d\n", timersElapsed);
int timersElapsed is 4 bytes. Reading 8 bytes into this results in a stack overflow, giving unpredictable behaviour.
Changing timersElapsed to a long int and fixing the printf did the trick for me.
long int timersElapsed = 0;
(void) read(p.fd, &timersElapsed, 8);
printf("timers elapsed: %ld\n", timersElapsed);
This appears to be an issue with Fedora (or my installation of Fedora). That system is running 3.16, and poll() does not work.
However, on a separate Ubuntu installation with 3.13, the poll() code above works just fine. As I will be using Ubuntu in the future anyway, I will not try to track down the issue on Fedora. Though I am curious if others are seeing this same issue on Fedora systems.
I faced the same problem.
After debugging, the root cause in poll example is that
timerValue should be declared as uint64_t.
- int timersElapsed = 0;
+ uint64_t timersElapsed = 0;
The man page of timerfd_create() describes this.
Operating on a timer file descriptor
The file descriptor returned by timerfd_create() supports the following
operations:
read(2)
If the timer has already expired one or more times since its settings
were last modified using timerfd_settime(), or since the last suc‐
cessful read(2), then the buffer given to read(2) returns an unsigned
8-byte integer (uint64_t) containing the number of expirations that
have occurred. (The returned value is in host byte order—that is,
the native byte order for integers on the host machine.)

How to "bypass" pthreads limit number

I have a little problem here. I know Linux limits the number of threads of an user can actually run.
I'm using pthread_create and an array of pthread_t limited with 50 ( pthread_t tid[50]; ). I have a for cycle that each time that limit reaches 50 every thread on pthread_t array is killed.
How? I tested almost everything. with pthread_kill(tid[w],SIGKILL); w is a simple cycle control variable goes from 0 to 50. I already tested pthread_cancel(tid[w]); and the problem keeps.
So what is the problem?
Everytime I reach 380 thread number I can't create more. But I'm killing with cancel or kill. So what is happening?
The objective of the program is a network scanner. To be faster I need like 500 threads with like 2 seconds of timeout to test IP's and ports.
Anyone knows how to "go arround" this problem?
I thought that I could kill the thread it would solve the problem but I was wrong :(
Without use ulimit or in /proc/sys/kernel/threads_max changing values, I looked at pthread_attr_setstacksize but I'm a bit confused :P
any ideas?
EDIT
The code as requested :P
I'm going to put ALL code here:
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#ifndef SOL_TCP
#define SOL_TCP 6
#endif
#ifndef TCP_USER_TIMEOUT
#define TCP_USER_TIMEOUT 18 //retry
#endif
#define MAX_TH 250
struct ar_stc{
char* ip;
int port;
};
char* ret[2];
int porar[2];
pthread_t tid[MAX_TH];
void create_port_scan_th(char* host,int p,int j);
//cares about args.
//this is not helpful for the threads post on stackoverflow. skip this function
char** arguments_handle(int argc,char **arg)
{
char p[]="-p";
char h[]="-h";
size_t _p,_h;
_p=(size_t)strlen(p);
_h=(size_t)strlen(h);
if(argc!=5)
{
printf("Usage:./file -p PORT-RANGE -h HOST.IP\n");
exit(1);
}
if(strncmp(arg[1],p,_p)==0 || strncmp(arg[1],h,_h)==0 && strncmp(arg[3],p,_p)==0 || strncmp(arg[3],h,_h)==0)
{
if(strncmp(arg[1],p,_p)==0)
{
strncpy(ret[0],arg[2],strlen(arg[2]));
}
else
{
strncpy(ret[1],arg[2],strlen(arg[2]));
}
if(strncmp(arg[3],h,_h)==0)
{
strncpy(ret[1],arg[4],strlen(arg[4]));
}
else
{
strncpy(ret[0],arg[4],strlen(arg[4]));
}
}
return ret;
}
int* take_ports(char *arg)
{
char* ports[2];
ports[0] = malloc(5);
ports[1] = malloc(5);
memset(ports[0],0,5);
memset(ports[1],0,5);
char tmp[5];
int len = strlen(arg);
int i,j=0,x=0;
char min_p[5],max_p[5];
for(i=0;i<len;i++)
{
if(arg[i]=='-')
{
min_p[x]='\0';
j=1;
x=0;
continue;
}
else
{
if(j==0)
min_p[x]=arg[i];
else
max_p[x]=arg[i];
}
x++;
}
max_p[x]='\0';
porar[1]=atoi(max_p);
porar[0]=atoi(min_p);
free(ports[0]);
free(ports[1]);
return porar;
}
void *check_port(void* ar_p)
{
struct ar_stc *ar =ar_p;
char* ip = ar->ip;
int port = ar->port;
int s,conexao;
int timeout = 1000; //1 second timeout
s=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in dst;
setsockopt(s,SOL_TCP,TCP_USER_TIMEOUT,(char*)&timeout,sizeof(timeout)); //NOT WORKING :(
if(s<0)
{
printf("\nCouldnt create socket\nPremissions maybe?\n");
exit(1);
}
dst.sin_family = AF_INET;
dst.sin_port = htons(port);
dst.sin_addr.s_addr = inet_addr(ip);
bzero(&(dst.sin_zero),8);
//printf("\nChecking: %d...",port);
conexao = connect(s,(struct sockaddr*)&dst,sizeof(dst));
if(conexao <0)
{
printf("TCP/%d:CLOSED!\n",port); //just to make sure the thread is running
close(s);
return;
}
else
{
printf("TCP/%d:OPEN!\n",port);
close(s);
return;
}
}
int main(int argc, char **argv)
{
int open_ports[65535];
int open_ports_count=0;
int min_p,max_p;
int* p;
ret[0] = malloc(20);
ret[1] = malloc(20);
memset(ret[0],0,20);
memset(ret[1],0,20);
char** ipnport;
ipnport = arguments_handle(argc,argv);
printf("The IP is :%s and the range is %s\n",ipnport[1],ipnport[0]);
p=take_ports(ipnport[0]);
min_p=p[0];
max_p=p[1];
printf("Min port:%d e max port:%d\n",min_p,max_p);
int i;
int thread_count=-1;
for(i=min_p;i<=max_p;i++)
{
thread_count++;
create_port_scan_th(ipnport[1],i,thread_count);
if(thread_count>=MAX_TH)
{
sleep(1);
thread_count=0;
int w;
for(w=0;w<=MAX_TH;w++)
{
pthread_kill(tid[w],SIGKILL);
}
}
}
free(ret[0]);
free(ret[1]);
return 0x0;
}
void create_port_scan_th(char* host,int p,int j)
{
int error;
struct ar_stc *ar;
ar = malloc(sizeof(*ar));
ar->ip=host;
ar->port=p;
error = pthread_create(&(tid[j]),NULL,&check_port,(void*)ar);
if(error!=0)
printf("\nError creating thread:%s\n",strerror(error));
}
But I'm killing with cancel or kill.
First of all, pthread_kill does not kill or end a thread.
(see more at pthread_kill doesnt kill thread C linux or When to use pthread_cancel and not pthread_kill).
If you send SIGKILL to a thread, the entire process will end.
To end a thread, you need to
Make the thread end.
by returning from the thread function, or
calling pthread_exit or
pthread_cancel the thread
Dispose the resources tied to the thread by:
Call pthread_join() on the thread or
make the thread a detached thread.
If you opt for the last point by making the thread detached - which will automatically release the thread when it ends , you can call pthread_detach(pthread_Self()) at the start of your thread function.
Or supply a pthread_attr_t when you call pthread_create(), where you set the thread to a detached state.
As for the total number of threads you can use, linux have a limit on the total number of threads/processes any user can have running.
You can view this with the command ulimit -u

Resources