I want to use the it_interval of newValue to set the interval of the timeout.
But in my example, I can only print timeout once.
What happened? How can I set the interval?
This is my code:
int main()
{
int efd =epoll_create(256);
setnonblock(efd);
struct epoll_event ev,events[256];
int tfd;//timer fd
if((tfd= timerfd_create(CLOCK_MONOTONIC,TFD_NONBLOCK)) < 0)
cout<<"timerfd create error"<<endl;
struct itimerspec newValue;
struct itimerspec oldValue;
bzero(&newValue,sizeof(newValue));
bzero(&oldValue,sizeof(oldValue));
struct timespec ts;
ts.tv_sec = 5;
ts.tv_nsec = 0;
//both interval and value have been set
newValue.it_value = ts;
newValue.it_interval = ts;
if( timerfd_settime(tfd,0,&newValue,&oldValue) <0)
{
cout<<"settime error"<<strerror(errno)<<endl;
}
ev.data.fd = tfd;
ev.events = EPOLLIN | EPOLLET;
if( epoll_ctl(efd,EPOLL_CTL_ADD,tfd,&ev) < 0)
cout<<"epoll_ctl error"<<endl;
int num = 0;
while(1)
{
if((num=epoll_wait(efd,events,256,1000)) > 0)
{//justice
for(int i=0;i<num;i++)
{
if(events[i].data.fd == tfd)
{
cout<<"timeout"<<endl;
}
}
}
}
return 0;
}
It is because you are using EPOLLET and not read()ing the data produced into the tfd. The expiration of a timer "writes" 8 bytes of data that need to be read: you really need to read it. Add this when you print "timeout":
uint64_t value;
read(tfd, &value, 8);
In more details: EPOLLET asks for Edge Triggering, which means that epoll_wait() will say only once "data is ready for input" on the file descritor tfd until you read that data. In other words, as long as you didn't read that data, future calls to epoll_wait() will not return the same descriptor again. This behavior is useful with normal sockets, e.g. if you do epoll_wait() in the main thread, notice some data is ready, then fire up another thread to read it. The main thread goes immediately back to epoll_wait(). But we don't want it to wake up immediately again, even though the data from the file descriptor was probably not read yet.
Note that I guess your example without EPOLLET would be wrong too, differently: because you don't read(), the tfd is always readable after the initial delay, and so it would print "timeout" as fast as possible after the initial delay expires.
Related
I have to implement a conversion tool between two different protocols.
It should be a relatively simply loop, triggered by filedescriptor events.
The protocol APIs however:
st API: Is meant for use with select(), it expose a GetFD() method that will throw it fd's into the given fd_set using FD_SET
nd API: Only works with poll() (it is ZMQ)
Is there any way to extract the fds from a fd_set, without calling select()? (Preferably portable)
I have tried looking into the source of the fd_set structure, but it is not really readable and probably a hint that you should not touch it through anything than the 4 macro, FD_CLR/SET/ISSET/ZERO.
//Pseudo-code of what i hope to achieve
// Get fd's from API1
fd_set readfds;
FD_ZERO( & readfds );
int max = api1.GetFd(readfds);
struct zmq_pollitem_t poll_items[MAX_COUNT];
int fd_count = 0;
convert_fdset_to_pollitem( readfds , poll_items , fd_count ); //what i need
poll_items[fd_count].fd = api2.GetFD();
poll_items[fd_count].socket = api2.GetSocket();
fd_count++;
const uint32_t timeout_msec = 500;
int ret = zmq_poll( poll_items , fd_count , timeout_msec);
An example of a select() function. You can compare the return then with each of your different protocol sockets - e.g. if (select_socket(s1,s2) == protocol_1_sd). I am using that function, to handle http and https sockets.
// selecting corresponding socket from FD_SET
int select_socket(int sock_1, int sock_2) {
fd_set read;
struct timeval timeout;
int ret = -1;
FD_ZERO(&read);
FD_SET(sock_1, &read);
FD_SET(sock_2, &read);
timeout.tv_sec= 10;
timeout.tv_usec = 0;
if (select(FD_SETSIZE, &read, NULL, NULL, &timeout ) < 0)
perror("select");
for (int i = 0; i < FD_SETSIZE; i++) {
if (FD_ISSET(i, &read)) {
if (i == sock_1)
ret = sock_1;
else if (i == sock_2)
ret = sock_2;
else {
FD_CLR(i, &read);
ret = -1;
}
}
}
return ret;
}
FIRST see below EDIT part.
I use beaglebone black, ker 3.8, and GCC compiler for a signal processing project.
I receive the raw data from three GPS modules through uart communication asynchronously. So, I used 3 threads which check 3 UARTs (BB-UART1, BB-UART2, BB-UART4) continuously to receive raw data, here called the "reading threads". after each data packet received from each module, I decode the received data packet and extract important data packet.
when, decoding is finished in the threads, I perform the signal processing in a separate thread, called "signal processing thread", using above 3-important decoded data packet.
as it's obvious, I should synchronize the reading threads with signal processing thread. I use pthread_cond_wait and pthread_cond_signal for that.
the code operates fine and synchronization and signal processing are performed efficiently. each data packet received in 0.1 second (10 times in a second).
In the signal processing thread, after signal processing, I send the signal processing result to the user through separate UART, BB-UART5.
when I add this part of the code, "THIS" line, after some time, which all parts or OK and the signal processing results are sent to user, the signal processing thread is frozen and locked in a mutex. In fact the mutex unlocking is not performed in previous step.
I spent many time, some weeks, to find the reason. when I remove the mutex and other tools for threads synchronization (to make the whole code simple to debug) an array of data in somewhere is overflowed and its data are changed to overflowed values. However when I don't add "THIS" line, overflow not occurred any time.
when I remove the "write" function (of BB-UART5) in signal processing thread all operations are OK.
the signal processing thread:
void *signal_processing_thread (void *arg){
int i, j;
char str[512];
printf("000000000000000000000000000000000000000000\r\n");
printf("0-signal_processing_thread is running!\r\n");
printf("000000000000000000000000000000000000000000\r\n");
while(1){
pthread_mutex_lock(&th1); // the code lock here after add "THIS" line
pthread_mutex_lock(&th2);
pthread_mutex_lock(&th3);
if ((!decode_completed[0])|(!decode_completed[1])|(!decode_completed[2])){
pthread_mutex_unlock(&th1);
pthread_mutex_unlock(&th2);
pthread_mutex_unlock(&th3);
continue;
}
// data packets are ready in reading threads
// signal processing start
// signal processing done
// send the results
sprintf (str,"some string\r\n\0",some variables);
printf (str);
for (i=0;i<256;i++)
if (str[i]==0)
break;
write (uart5_id, str, i); // "THIS" line
decode_completed [0] = 0;
decode_completed [1] = 0;
decode_completed [2] = 0;
pthread_cond_signal(&cv1);
pthread_mutex_unlock(&th1);
pthread_cond_signal(&cv2);
pthread_mutex_unlock(&th2);
pthread_cond_signal(&cv3);
pthread_mutex_unlock(&th3);
}
printf("signal processing thread is closed!\r\n");
}
the reading threads:
void *getdecodedata1_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("1-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th1);
while(1){
for (i=0;i<500;i++){
ret = read(uart1_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode1[count_decode3+i]=buffer[i];
count_decode1 += count;
if (count_decode1>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [0] = 1; // newdata
printf("WAIT_1\n");
pthread_cond_wait(&cv1,&th1);
pthread_mutex_unlock(&th1);
pthread_mutex_lock(&th1);
printf("RELEASE_1\n");
}
}
}
void *getdecodedata2_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("2-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th2);
while(1){
for (i=0;i<500;i++){
ret = read(uart2_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode3[count_decode2+i]=buffer[i];
count_decode2 += count;
if (count_decode2>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [1] = 1; // newdata
printf("WAIT_2\n");
pthread_cond_wait(&cv2,&th2);
pthread_mutex_unlock(&th2);
pthread_mutex_lock(&th2);
printf("RELEASE_2\n");
}
}
}
void *getdecodedata3_thread (void *arg){
int ret, count, count_decode=0;
char buffer[2024], buffer_decode[2024];
int i;
printf("3-getdecodedata_thread is running!\r\n");
count = 0;
pthread_mutex_lock(&th3);
while(1){
for (i=0;i<500;i++){
ret = read(uart4_id, buffer+count ,255);
if (ret<1)
continue;
// data received
count += ret;
if (count>1000) break;
}
if (count>0){ // packet received
for (i=0;i<count;i++)
buffer_decode3[count_decode3+i]=buffer[i];
count_decode3 += count;
if (count_decode3>15){
// decode
// ....
// decode done
}
count = 0;
}
if (decode is completed) {
decode_completed [2] = 1; // newdata
printf("WAIT_3\n");
pthread_cond_wait(&cv3,&th3);
pthread_mutex_unlock(&th3);
pthread_mutex_lock(&th3);
printf("RELEASE_3\n");
}
}
}
EDIT: I've found that the problem is in another place of the code. in some where I use "write" function to send some bytes to UART5 and in a separate thread I read simultaneously (non-blocking) UART5 to receive commands. I think a problem like "SegFault" is occurred and the above problem is seen. when I comment the "read" function of UART5, all things is correct and mutexes work finely. How can I use the UART5 to read and write simultaneously?
after about 2 months, I find that the problem is originated from an invalid event in an IC. I use a ttl to RS485 converter and its supply bus has sum noise and distortion which leads to send some invalid characters to serial input. In-fact when I send some characters using serial output, I think probably, serial input receive some invalid data. so it freezes the code in one of critical condition mechanisms. when I make the IC separate from the BBB, the problem is fixed.
I don't Know why? and How? How can a invalid data on serial input can make critical conditions lock? I use ttyO[] files to read and write the serial port.
I have written a program to scan kernel memory for a pattern from user space. I run it from root. I expect that it will generate SIGSEGVs when it hits pages that aren't accessible; I would like to ignore those faults and just jump to the next page to continue the search. I have set up a signal handler that works fine for the first occurrence, and it continues onward as expected. However, when a second SIGSEGV occurs, the handler is ignored (it was reregistered after the first occurrence) and the program terminates. The relevant portions of the code are:
jmp_buf restore_point;
void segv_handler(int sig, siginfo_t* info, void* ucontext)
{
longjmp(restore_point, SIGSEGV);
}
void setup_segv_handler()
{
struct sigaction sa;
sa.sa_flags = SA_SIGINFO|SA_RESTART|SA_RESETHAND;
sigemptyset (&sa.sa_mask);
sa.sa_sigaction = &segv_handler;
if (sigaction(SIGSEGV, &sa, NULL) == -1) {
fprintf(stderr, "failed to setup SIGSEGV handler\n");
}
}
unsigned long search_kernel_memory_area(unsigned long start_address, size_t area_len, const void* pattern, size_t pattern_len)
{
int fd;
char* kernel_mem;
fd = open("/dev/kmem", O_RDONLY);
if (fd < 0)
{
perror("open /dev/kmem failed");
return -1;
}
unsigned long page_size = sysconf(_SC_PAGESIZE);
unsigned long page_aligned_offset = (start_address/page_size)*page_size;
unsigned long area_pages = area_len/page_size + (area_len%page_size ? 1 : 0);
kernel_mem =
mmap(0, area_pages,
PROT_READ, MAP_SHARED,
fd, page_aligned_offset);
if (kernel_mem == MAP_FAILED)
{
perror("mmap failed");
return -1;
}
if (!mlock((const void*)kernel_mem,area_len))
{
perror("mlock failed");
return -1;
}
unsigned long offset_into_page = start_address-page_aligned_offset;
unsigned long start_area_address = (unsigned long)kernel_mem + offset_into_page;
unsigned long end_area_address = start_area_address+area_len-pattern_len+1;
unsigned long addr;
setup_segv_handler();
for (addr = start_area_address; addr < end_area_address;addr++)
{
unsigned char* kmp = (unsigned char*)addr;
unsigned char* pmp = (unsigned char*)pattern;
size_t index = 0;
for (index = 0; index < pattern_len; index++)
{
if (setjmp(restore_point) == 0)
{
unsigned char p = *pmp;
unsigned char k = *kmp;
if (k != p)
{
break;
}
pmp++;
kmp++;
}
else
{
addr += page_size -1;
setup_segv_handler();
break;
}
}
if (index >= pattern_len)
{
return addr;
}
}
munmap(kernel_mem,area_pages);
close(fd);
return 0;
}
I realize I can use functions like memcmp to avoid programming the matching part directly (I did this initially), but I subsequently wanted to insure the finest grained control for recovering from the faults so I could see exactly what was happening.
I scoured the Internet to find information about this behavior, and came up empty. The linux system I am running this under is arm 3.12.30.
If what I am trying to do is not possible under linux, is there some way I can get the current state of the kernel pages from user space (which would allow me to avoid trying to search pages that are inaccessible.) I searched for calls that might provide such information, but also came up empty.
Thanks for your help!
While longjmp is perfectly allowed to be used in the signal handler (the function is known as async-signal-safe, see man signal-safety) and effectively exits from the signal handling, it doesn't restore signal mask. The mask is automatically modified at the time when signal handler is called to block new SIGSEGV signal to interrupt the handler.
While one may restore signal mask manually, it is better (and simpler) to use siglongjmp function instead: aside from the effect of longjmp, it also restores the signal mask. Of course, in that case sigsetjmp function should be used instead of setjmp:
// ... in main() function
if(sigsetjmp(restore_point, 1)) // Aside from other things, store signal mask
// ...
// ... in the signal handler
siglongjmp(restore_point); // Also restore signal mask as it was at sigsetjmp() call
I have an assignment to implement Producer consumer problem in a convoluted way(may be to test my understanding). The parent process should set up a shared memory. The unnamed semaphores(for empty count and filled count) should be initialized and a mutex should be initialized. Then two child processes are created, a producer child and a consumer child. Each child process should create a new thread which should do the job.
PS: I have read that the semaphore's should be kept in a shared memory as they would be shared by different processes.
Please provide some hints, or suggest changes.
So far, I have done this:
struct shmarea
{
unsigned short int read;
unsigned short int max_size;
char scratch[3][50];
unsigned short int write;
sem_t sem1;// Empty slot semaphore
sem_t sem2;// Filled slot Semaphore
};
void *thread_read(void* args);
void *thread_write(void *args);
pthread_mutex_t work_mutex;
struct shmarea *shma;
int main()
{
int fork_value,i=0,shmid;
printf("Parent process id is %d\n\n",getpid());
int res1,res2;
key_t key;
char *path = "/tmp";
int id = 'S';
key = ftok(path, id);
shmid = shmget(key,getpagesize(),IPC_CREAT|0666);
printf("Parent:Shared Memory id = %d\n",id);
shma = shmat(shmid,0,0);
shma->read = 0;
shma->max_size = 3;
shma->write = 0;
pthread_t a_thread;
pthread_t b_thread;
void *thread_result1,*thread_result2;
res1 = sem_init(&(shma->sem1),1,3);//Initializing empty slot sempahore
res2 = sem_init(&(shma->sem2),1,0);//Initializing filled slot sempahore
res1 = pthread_mutex_init(&work_mutex,NULL);
while(i<2)
{
fork_value = fork();
if(fork_value > 0)
{
i++;
}
if(fork_value == 0)
{
if(i==0)
{
printf("***0***\n");
//sem_t sem1temp = shma->sem1;
char ch;int res;
res= pthread_create(&a_thread,NULL,thread_write,NULL);
}
if(i==1)
{
printf("***1***\n");
//sem_t sem2temp = shma->sem2;
int res;
char ch;
res= pthread_create(&b_thread,NULL,thread_read,NULL);
}
}
}
int wait_V,status;
res1 = pthread_join(a_thread,&thread_result1);
res2 = pthread_join(b_thread,&thread_result2);
}
void *thread_read(void *args)
{
while(1)
{
sem_wait(&(shma->sem2));
pthread_mutex_lock(&work_mutex);
printf("The buf read from consumer:%s\n",shma->scratch[shma->read]);
shma->read = (shma->read+1)%shma->max_size;
pthread_mutex_unlock(&work_mutex);
sem_post(&(shma->sem1));
}
}
void *thread_write(void *args)
{
char buf[50];
while(1)
{
sem_wait(&(shma->sem1));
pthread_mutex_lock(&work_mutex);
read(STDIN_FILENO,buf,sizeof(buf));
strcpy(shma->scratch[shma->write],buf);
shma->write = (shma->write+1)%shma->max_size;
pthread_mutex_unlock(&work_mutex);
sem_post(&(shma->sem2));
}
}
(1) Your biggest problem by far is that you have managed to write a fork bomb. Because you don't exit either child in the fork loop each child is going to fall through and loop around and create their own children until you crash or bring the system down. You want something more like this:
while(i < 2)
{
fork_value = fork();
if(fork_value > 0)
i++;
if(fork_value == 0)
{
if(i==0)
{
printf("0 child is pid %d\n", getpid());
int res;
res = pthread_create(&a_thread,NULL,thread_write,NULL);
res = pthread_join(a_thread,&thread_result1);
exit(0);
}
if(i==1)
{
printf("1 child is pid %d\n", getpid());
int res;
res = pthread_create(&b_thread,NULL,thread_read,NULL);
res = pthread_join(b_thread,&thread_result2);
exit(0);
}
}
}
for (i = 0; i < 2; ++i)
wait(NULL);
Notice the wait on the children which you neglected.
(2) Always check your return codes. They are like safety belts, a bit of a drag but so helpful when you crash. (Yes, I didn't take my advice here but you should.)
(3) These names are awful.
unsigned short int read;
unsigned short int write;
Stay away from naming variables after system calls. It's confusing and just asking for trouble.
(4) Terminology wise, processes with a common ancestor, like these, are related. The parent can open shared memory and other resources and pass it on to the children. Unrelated processes would, for example, multiple instances of program launched from different terminals. They can share resources but not in the "inherited" way forked processes do.
It's late and didn't get around to looking at what you are doing with the threads and such but this should get you started.
I'm implementing a misc device driver for linux.
This driver implements file_operations::poll and
I want to make it so that poll(2) would return POLLHUP if the descriptor is closed.
Supposed driver client code(userland code) follows.
void ThreadA(int fd){
// initialization codes...
pfd[0].fd = fd;
pfd[0].event = POLLIN;
int r = poll(pfd, 1, -1);
if(r > 0 && pfd[0].revent & POLLHUP){
// Detect fd is closed
return; // Exit thread
}
}
void ThreadB(int fd){
// waiting some events. ex.signals
// I expect close(fd) will cause poll(2) return and ThreadA will exit.
close(fd);
return;
}
But I could not implement this behavior to in my driver code.
Calling poll(2) never returns even if descriptor is closed. so threadA never exits.
Trivial test driver code follows.
static wait_queue_head_t q;
static int CLOSED = 0;
int my_open(struct inode *a, struct file *b){
printk(KERN_DEBUG "my_open");
return 0;
}
int my_release(struct inode *a, struct file *b){
printk(KERN_DEBUG "my_release");
CLOSED = 1;
wake_up_interruptible(&q);
// I expect this call will wake up q and recall my_poll.
// but doesn't
return 0;
}
unsigned int my_poll(struct file *a, struct poll_table_struct *b){
printk(KERN_DEBUG "my_poll");
poll_wait(file, &q, a);
if(CLOSED != 0)
return POLLHUP;
return 0;
}
static const struct file_operations my_fops = {
.owner = THIS_MODULE,
.open = &my_open,
.release = &my_release,
.poll = &my_poll
};
static struct miscdevice mydevice =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "TESTDEV",
.fops = &my_fops
};
static int __init myinit(void){
init_waitqueue_head(&q);
misc_register(&mydevice);
return 0;
}
static void __exit myexit(void){
misc_deregister(&mydevice);
}
module_init(myinit);
module_exit(myexit);
MODULE_LICENSE("GPL");
I think calling wake_up_interruptible() doesn't effect in my_release().
so that my_poll() will never be recalled and poll(2) will never return.
How should I implement my_poll() in a correct manner?
My test environment:
kernel is linux-3.10.20
The manual page for close warns:
It is probably unwise to close file descriptors while they may be in use by
system calls in other threads in the same process. Since a file descriptor
may be reused, there are some obscure race conditions that may cause unintended
side effects.
I suspect that something in the higher levels of the kernel is cancelling your poll operation when you execute close, before the release() function actually gets called. I'd think about solving your problem a different way.