I have a sample program which creates a pthread, waits for the thread to join. The thread will invoke phread_cond_timedwait() to wait for 2 seconds. On Linux platforms, the sample code works fine. On FreeBSD, the call returns immediately with EPERM error code.
pthread_condition_timedwait.cpp
#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
void *thread_handler(void *ptr){
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
struct timespec ts;
struct timeval tp;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec*1000;
ts.tv_sec += 2;
//Invoke pthread_cond_timedwait() to wait for 2 seconds
int rcode = pthread_cond_timedwait(&cond, &mutex, &ts);
if (rcode == ETIMEDOUT)
printf("Terminated due to time out\n");
else if (rcode == EPERM)
printf("Terminated due to EPERM\n");
else
printf("Return code is %d\n", rcode);
return NULL;
}
int main(int argc, char** argv){
pthread_t thread;
// start the thread
pthread_create(&thread, NULL, &thread_handler, NULL);
// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
EPERM is returned if the thread that calls timedwait does not own the mutex. You must lock the mutex before calling timedwait. Also, move the static initialization of mutex and condvar to file scope.
UPDATE: If you initialize the mutex to be an error-checking mutex, Linux will also terminate with EPERM (since it is UB to call pthread_cond_wait/timedwait without holding the mutex).
Modified code below:
//#define _BSD_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex;
void *thread_handler(void *ptr){
struct timespec ts;
struct timeval tp;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec*1000;
ts.tv_sec += 2;
//Invoke pthread_cond_timedwait() to wait for 2 seconds
int rcode = pthread_cond_timedwait(&cond, &mutex, &ts);
if (rcode == ETIMEDOUT)
printf("Terminated due to time out\n");
else if (rcode == EPERM)
printf("Terminated due to EPERM\n");
else
printf("Return code is %d\n", rcode);
return NULL;
}
int main(int argc, char** argv){
pthread_mutexattr_t mta;
pthread_mutexattr_init(&mta);
pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &mta);
pthread_t thread;
// start the thread
pthread_create(&thread, NULL, &thread_handler, NULL);
// wait for thread to finish
pthread_join(thread, NULL);
return 0;
}
Tested on kernel SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux, distro Debian GNU/Linux buster/sid.
I am trying to use libevent for manage the serial communication between an embedded Linux device and a pc.
First problem with libevent. I've created a C Project in eclipse , in the main I am creating some events and it is ok for the compiler:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <event.h>
#include "function_test.h"
....
int main(void) {
struct event ev_sighup; //reports that the user's terminal is disconnected
struct event ev_sigterm; //program termination
struct event ev_sigint; // program interrupt
int rv = 0;
/* Set up libevent & signal handling */
event_init();
event_set(&ev_sighup, SIGHUP, EV_SIGNAL, peripherals_end, NULL);
event_add(&ev_sighup, NULL);
event_set(&ev_sigterm, SIGTERM, EV_SIGNAL, peripherals_end, NULL);
event_add(&ev_sigterm, NULL);
event_set(&ev_sigint, SIGINT, EV_SIGNAL, peripherals_end, NULL);
event_add(&ev_sigint, NULL);
.....
}
But then, in "function_test.c":
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <event.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include "function_test.h"
.....
/*serial file descriptor */
int 232_fd= -1;
/* Event triggered when data is available */
struct event ev_rs232read;
.....
event_set(&ev_rs232read, 232_fd, EV_READ|EV_PERSIST, readRs232, NULL);
if ((rv = event_add(&stm32_ev_read, NULL)) < 0) {
// log error
return RTN_ERR;
}
return RTN_OK;
}
And misteriously Eclipse doesn't finds event.h (only in function_test.c) and thereby I got the next errors:
warning: implicit declaration of function ‘event_set’
../src/function_test.c:114: error: ‘EV_READ’ undeclared (first use in this function)
../src/function_test.c:114: error: (Each undeclared identifier is reported only once
../src/function_test.c:114: error: for each function it appears in.)
../src/function_test.c:114: error: ‘EV_PERSIST’ undeclared (first use in this function)
...
Does this bug repeats during the compilation with GNU Autotools or just simple Makefile?
How to change the value of the tos bits in the ip header?
I tried directly modifying it using the iphdr structure.
It is done at the kernel level using netfilter.
The code I wrote is as follows:
// Including the required header files
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/in.h>
#include <linux/inet.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <net/sock.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/proc_fs.h>
// Defining the name of the module
#define MODULE_NAME "TOS_setter"
// Structure definition for processing outgoing packets
static struct nf_hook_ops nf_ops_out;
//===========================================================
// Function that modifies the TOS bits
unsigned int tos_setter(unsigned int hooknum,struct sk_buff *skb, const struct net_device *in,
const struct net_device *out,int (*okfn)(struct sk_buff*))
{
struct iphdr *iph;
unsigned char tosbits;
if (!skb)return NF_ACCEPT;
iph = ip_hdr(skb);
if (!iph)return NF_ACCEPT;
//if(iph->protocol==IPPROTO_TCP)return NF_ACCEPT;
if (iph->protocol==IPPROTO_TCP)
{
printk(KERN_ALERT " The total length is : %d\n" , (int)iph->tot_len);
iph->tos = tosbits | (unsigned char)2;
tosbits = iph->tos;
printk(KERN_ALERT " The tos bits are : %d\n" , (int)tosbits);
printk(KERN_ALERT " The total length is : %d\n" , (int)iph->tot_len);
}
return NF_ACCEPT;
}
//===========================================================
//Initialisation function
static int __init init(void){
printk(KERN_ALERT " Initialization Started \n");
// Initialize Hook Functions
nf_ops_out.hook = tos_setter;
nf_ops_out.pf = PF_INET;
nf_ops_out.hooknum =4;
nf_ops_out.priority = NF_IP_PRI_FIRST;
// Register the Hook functions
nf_register_hook(&nf_ops_out);
printk(KERN_ALERT "hook functions registered\n");
printk(KERN_ALERT " KSTAT Initialization Completed \n");
return 0;
}
static void __exit cleanup(void){
printk(KERN_ALERT "KSTAT Exit Started\n");
// Unregister the hook functions
nf_unregister_hook(&nf_ops_out);
printk("Unregistered the hooks\n");
printk(KERN_ALERT "KSTAT Exit Completed\n");
}
/* init and cleanup functions */
module_init(init);
module_exit(cleanup);
MODULE_LICENSE("GPL");
The problem is that when I try to change the value of the tos bits my internet stops working.
Is there any other way or if anyone can point out what i am doing wrong it will be really helpful.
You have to re-calculate the IP header checksum after you change anything in the header.
See WP: http://en.wikipedia.org/wiki/IPv4_header_checksum
Code is here: How do I compute an RFC 791 IP header checksum?
You can use incremental IP checksum, i.e: since the IP checksum is a sum, you can substract the old value and add the new one. Linux supports that with the csum_replace*() functions in net/checksum.h. Just do:
csum_replace2(&iph->check, htons(oldtos), htons(iph->tos));
I've been learning OpenGL the past few weeks and after reading the Swiftless tuts and part of Nehe's tuts, along side with other articles concerning normals, scene graphs, bla bla, i've decided to create some sort of "framework", to allow me to insert newly learned code easier. So I decided to create a scenegraph/renderer combo, not that pretty, not that fast (prolly), but with the option to add just a new derived node class to render a new whatever feature i might just have read. So i look on the interwebz to see various examples on how to implement one and settle on this base class:
#pragma once
#ifndef NODE_H
#define NODE_H
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include <list>
using namespace std;
class Node
{
public:
Node(void);
~Node(void);
//Node* parent;
void addChild(Node* node);
void removeChilds(Node* node);
virtual void traverse();
void kill();
protected:
std::list<Node*> childs;
};
#endif
.... from which i made this class:
#pragma once
#ifndef NODESPHERE_H
#define NODESPHERE_H
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include "Various.h"
#include "Node.h"
class NodeSphere : public Node
{
public:
NodeSphere(double R, double H, double K, double Z, const int space);
~NodeSphere(){delete this;}
void traverse();
private:
float out[3];
int Radius;
int vhVertexCount;
Vert *vhVertices;
Normal *vhNormals,*vhVNormals;
TexCoord *vhTexCoords;
unsigned int vhVBOVertices;
unsigned int vhVBOTexCoords;
unsigned int vhVBONormals;
bool Init(void);
bool Normals(const int nIndex);
bool ReduceToUnit(void);
};
#endif
Now, i use freeglut to handle the window creation and the loop:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include "Scenegraph.h"
#include "View.h"
#include "Control.h"
#define WIDTH 800
#define HEIGHT 600
Scenegraph *bob;
View *myView;
Control *controler;
.................
.................
void main(int argc, char **argv)
{
glewInit();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(WIDTH,HEIGHT);
glutInitWindowPosition(0,0);
glutCreateWindow("Mediensoftware - Finale Übung");
bob = new Scenegraph();
myView = new View(WIDTH, HEIGHT, bob);
controler = new Control(myView);
glutDisplayFunc(display);
glutIdleFunc(idle);
glutReshapeFunc(resize);
glutKeyboardFunc(keyboard);
glutSpecialFunc(keyboard_s);
glutMainLoop();
}
The Scenegraph "bob" handles the creation of nodes like this:
Scenegraph::Scenegraph()
{
this->root = new Node();
this->sun = new NodeSphere(3,0,0,0,10);
this->sun_transform = new NodeTransform();
this->sun_tex = new NodeTexture("sunmap.bmp");
this->sun_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
this->planet_earth = new NodeSphere(1,0,0,0,10);
this->planet_earth_transform = new NodeTransform(6,0,0);
this->planet_earth_tex = new NodeTexture("earthmap.bmp");
this->planet_earth_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
this->moon = new NodeSphere(0.3,0,0,0,10);
this->moon_tex = new NodeTexture("moonmap.bmp");
this->moon_transform = new NodeTransform(1.5,0,0);
this->moon_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
this->planet_venus = new NodeSphere(0.8,0,0,0,10);
this->planet_venus_transform = new NodeTransform(3,0,0);
this->planet_venus_tex = new NodeTexture("venusmap.bmp");
this->planet_venus_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
this->planet_mars = new NodeSphere(0.6,0,0,0,10);
................................................................................................
this->root->addChild(this->sun_transform);
this->sun_transform->addChild(this->sun_mat);
this->sun_mat->addChild(this->sun_tex);
this->sun_tex->addChild(this->sun);
this->sun->addChild(this->planet_venus_transform);
this->planet_venus_transform->addChild(this->planet_venus_mat);
this->planet_venus_mat->addChild(this->planet_venus_tex);
...................................................................................................
}
The compiler doesn't see any errors and executes the code, but it receives an access violation here:
bool NodeSphere::Init(void){
glGenBuffersARB(1, &vhVBOVertices); // DERP here
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOVertices);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVertices, GL_STATIC_DRAW_ARB);
glGenBuffersARB(1, &vhVBONormals);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBONormals);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVNormals, GL_STATIC_DRAW_ARB);
glGenBuffersARB(1, &vhVBOTexCoords);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOTexCoords);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 2 * sizeof(float), this->vhTexCoords, GL_STATIC_DRAW_ARB);
delete [] vhVertices;
vhVertices = NULL;
delete [] vhTexCoords;
vhTexCoords = NULL;
delete [] vhNormals;
vhNormals = NULL;
delete [] vhVNormals;
vhVNormals = NULL;
return true;
}
The extensions are called in the View::initExtensions(), the init of the Scenegraph is done after the window creation, so.... i'm pretty sure it has something to do with pointers...
on previous programs i used the exact same code for VBO creation and it worked. The only difference is that the code used here is used in a Node*, while the previous ones were used in just Node (no pointer). But in any case, i'm gonna check if glew starts up well.
As for what video card i am using, on the laptop i have a crappy Intel integrated card, which should support OpenGL 1.5, but doesn't even have GLSL, and on the PC, a 6850. The thing is that i work a lot on the laptop, because of faculty and other stuff as well.
But anyway, the code for creating VBO's works, i mean, it has worked for the following:
#include <stdlib.h>
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/gl.h> // Header File For The OpenGL32 Library
#include <GL/glu.h> // Header File For The GLu32 Library
#include <GL/glext.h>
#include <math.h>
#define PI 3.14159265f
class Vert{
public:
float x;
float y;
float z;
};
class Normal{
public:
float x;
float y;
float z;
};
class TexCoord{
public:
float u;
float v;
};
class Scenegraph {
private:
float out[3];
int Radius;
GLuint tID[2];
int vhVertexCount;
Vert *vhVertices;
Normal *vhNormals,*vhVNormals;
TexCoord *vhTexCoords;
unsigned int vhVBOVertices;
unsigned int vhVBOTexCoords;
unsigned int vhVBONormals;
bool Init(void);
bool Normals(const int nIndex);
bool ReduceToUnit(void);
public:
bool Create(double R, double H, double K, double Z, const int space);
void Render();
};
which is identical to NodeSphere, except it was statically declared. Thanks in advance.
Most likely, the error is occurring because the NodeSphere doesn't exist (or is no longer valid) when you try to call init().
You should probably move the resource initialization code into the constructor (that's generally what they're for) unless you need it to occur later on. It makes sense for the VBO to have a similar lifespan to the object, so creating and destroying them in the ctor/dtor should work and saves you the complexity of explicitly initializing.