I have 2 threads to decode RTSP stream video, my code as below:
int key = 0;
std::queue<AVpacket> Packet_buf;
int thread1 (void)
{
AVPacket packet;
packet = read_packet();
Packet_buf.push(packet);
av_packet_unref(&packet);
key = 1;
}
int thread2 (void)
{
AVPacket *packet;
while(key==0) {} // wait to read the first packet
*packet = Packet_buf.front(); // program halt here
avcodec_send_packet(pCodecCtx,packet);
}
int main();
{
thread p1(thread1);
thread p2(thread2);
}
My program crash at line: *packet = Packet_buf.front();
Can you help me to find the problem, Thanks !
Your code have more the one issues, some of them:
1) std::queue<AVpacket> Packet_buf;
I think this would be:
std::queue<AVPacket> Packet_buf; notice AVpacket and AVPacket is whole different thing. (Yes, I'm guessing this just a typo).
2) while(key==0) {} This is not a good way to wait on a variable change. Especially if the variable (key) is not volatile. It may work and probably is working. But I suggest you use pthread signal and condition variables here instead. Also check next issue (3) which is closely related.
3) *packet = Packet_buf.front(); Caling std::queue.front() before checking whether the container is empty() or not is NOT good idea. If container (queue) is empty than front() method here will result in undefined behavior.
Hope that helps.
Related
How can I see (on linux) which threads own a pthread_rwlock_t (or std::shared_mutex) ?
For a regular mutex there's Is it possible to determine the thread holding a mutex? but how to do this for a r/w lock?
Your good question has a few problems with a complete answer:
It is dependent upon which OS kernel you are running, and possibly even which version.
It is dependent upon which libc/libpthread you are using, and possibly even which compiler.
Presuming you can untangle a specific configuration above, we are looking at two different outcomes: there is a single writer, or a set of readers who currently cause pthread_rw_lock() to block for some callers.
In contrast, a mutex has only ever one owner and only that owner can release it.
So a first test in finding out whether your system has a findable owner set is to see if it actually records the ownership. A quick hack to this would be have one thread acquire the rwlock for read or write, then signal a second one to release it. If the release fails, your implementation properly records it, and you have a chance; if not, your implementation likely implements rwlocks with mutex + condvar + counter; so it has no idea of ownership.
So, some code:
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t lock;
pthread_cond_t cv;
pthread_rwlock_t rwl;
int ready;
void *rlse(void *_)
{
int *t = _;
pthread_mutex_lock(&lock);
while (ready == 0) {
pthread_cond_wait(&cv, &lock);
}
ready = 0;
pthread_cond_signal(&cv);
pthread_mutex_unlock(&lock);
*t = pthread_rwlock_unlock(&rwl);
return 0;
}
void *get(void *_)
{
int *t = _;
*t = (*t) ? pthread_rwlock_wrlock(&rwl) : pthread_rwlock_rdlock(&rwl);
if (*t == 0) {
pthread_mutex_lock(&lock);
ready = 1;
pthread_cond_signal(&cv);
while (ready == 1) {
pthread_cond_wait(&cv, &lock);
}
pthread_mutex_unlock(&lock);
}
return 0;
}
int main()
{
pthread_t acq, rel;
int v0, v1;
int i;
for (i = 0; i < 2; i++) {
pthread_rwlock_init(&rwl, 0);
pthread_mutex_init(&lock, 0);
pthread_cond_init(&cv, 0);
v0 = i;
pthread_create(&acq, 0, get, &v0);
pthread_create(&rel, 0, rlse, &v1);
pthread_join(acq, 0);
pthread_join(rel, 0);
printf("%s: %d %d\n", i ? "write" : "read", v0, v1);
}
return 0;
}
which we run as:
u18:src $ cc rw.c -lpthread -o rw
u18:src $ ./rw
read: 0 0
write: 0 0
This is telling us that in either case (rdlock, wrlock), a thread different from the calling thread can release the rwlock, thus it fundamentally has no owner.
With a little less sense of discovery, we could have found out a bit by reading the manpage for pthread_rwlock_unlock, which states that this condition is undefined behavior, which is the great cop-out.
Posix establishes a base, not a limit, so it is possible your implementation can support this sort of ownership. I program like the one above is a good investigative tool; if it turns up something like ENOTOWNER; but EINVAL would be pretty non-committal.
The innards of glic's rwlock (sysdeps/htl/bits/types/struct___pthread_rwlock.h):
struct __pthread_rwlock
{
__pthread_spinlock_t __held;
__pthread_spinlock_t __lock;
int __readers;
struct __pthread *__readerqueue;
struct __pthread *__writerqueue;
struct __pthread_rwlockattr *__attr;
void *__data;
};
confirms our suspicion; at first I was hopeful, with the queues and all, but a little diving through the code revealed them to be the waiting lists, not the owner lists.
The above was run on ubuntu 18.04; linux 4.15.0-112-generic; gcc 7.5.0; glibc 2.27 libpthread 2.27.
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.
The main question is: How we can wait for a thread in Linux kernel to complete? I have seen a few post concerned about proper way of handling threads in Linux kernel but i'm not sure how we can wait for a single thread in the main thread to be completed (suppose we need the thread[3] be done then proceed):
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/slab.h>
void *func(void *arg) {
// doing something
return NULL;
}
int init_module(void) {
struct task_struct* thread[5];
int i;
for(i=0; i<5; i++) {
thread[i] = kthread_run(func, (void*) arg, "Creating thread");
}
return 0;
}
void cleanup_module(void) {
printk("cleaning up!\n");
}
AFAIK there is no equivalent of pthread_join() in kernel. Also, I feel like your pattern (of starting bunch of threads and waiting only for one of them) is not really common in kernel. That being said, there kernel does have few synchronization mechanism that may be used to accomplish your goal.
Note that those mechanisms will not guarantee that the thread finished, they will only let main thread know that they finished doing the work they were supposed to do. It may still take some time to really stop this tread and free all resources.
Semaphores
You can create a locked semaphore, then call down in your main thread. This will put it to sleep. Then you will up this semaphore inside of your thread just before exiting. Something like:
struct semaphore sem;
int func(void *arg) {
struct semaphore *sem = (struct semaphore*)arg; // you could use global instead
// do something
up(sem);
return 0;
}
int init_module(void) {
// some initialization
init_MUTEX_LOCKED(&sem);
kthread_run(&func, (void*) &sem, "Creating thread");
down(&sem); // this will block until thread runs up()
}
This should work but is not the most optimal solution. I mention this as it's a known pattern that is also used in userspace. Semaphores in kernel are designed for cases where it's mostly available and this case has high contention. So a similar mechanism optimized for this case was created.
Completions
You can declare completions using:
struct completion comp;
init_completion(&comp);
or:
DECLARE_COMPLETION(comp);
Then you can use wait_for_completion(&comp); instead of down() to wait in main thread and complete(&comp); instead of up() in your thread.
Here's the full example:
DECLARE_COMPLETION(comp);
struct my_data {
int id;
struct completion *comp;
};
int func(void *arg) {
struct my_data *data = (struct my_data*)arg;
// doing something
if (data->id == 3)
complete(data->comp);
return 0;
}
int init_module(void) {
struct my_data *data[] = kmalloc(sizeof(struct my_data)*N, GFP_KERNEL);
// some initialization
for (int i=0; i<N; i++) {
data[i]->comp = ∁
data[i]->id = i;
kthread_run(func, (void*) data[i], "my_thread%d", i);
}
wait_for_completion(&comp); // this will block until some thread runs complete()
}
Multiple threads
I don't really see why you would start 5 identical threads and only want to wait for 3rd one but of course you could send different data to each thread, with a field describing it's id, and then call up or complete only if this id equals 3. That's shown in the completion example. There are other ways to do this, this is just one of them.
Word of caution
Go read some more about those mechanisms before using any of them. There are some important details I did not write about here. Also those examples are simplified and not tested, they are here just to show the overall idea.
kthread_stop() is a kernel's way for wait thread to end.
Aside from waiting, kthread_stop() also sets should_stop flag for waited thread and wake up it, if needed. It is usefull for threads which repeat some actions infinitely.
As for single-shot tasks, it is usually simpler to use works for them, instead of kthreads.
EDIT:
Note: kthread_stop() can be called only when kthread(task_struct) structure is not freed.
Either thread function should return only after it found kthread_should_stop() return true, or get_task_struct() should be called before start thread (and put_task_struct() should be called after kthread_stop()).
I am trying to write a simple D program with two threads (main and one spawned in main) with a daughter thread receiving message from the parent thread. Here is my piece:
import std.stdio;
import core.thread;
import std.concurrency;
import std.c.stdio;
extern (C) int kbhit();
void readSignal(){
for(;;){
bool stop = receiveOnly!bool();
if(!stop)
writeln("reading signal...");
else
writeln("stop reading signal...");
Thread.getThis.sleep(1.seconds);
}
}
int main()
{
auto reader = spawn(&readSignal);
bool stop = false;
while(true){
if(kbhit()){
stop = true;
}
option 1: reader.send(stop);
option 2: send(reader, stop);
}
}
return 0;
}
Basically I wait for a keyboard hit and the intend to pause the spawned thread.
Neither of options (option 1 by Andrei Alexandrescu and option 2 as in dlang docs) work for me. What do i do wrong?
It looks to me that your main thread is spinning very hard, sending thousands and thousands of messages to the reader. The reader, however, is only reading one per second. The 'true' message is backed up behind a massive number of 'false' messages.
For a situation like this, you may be better off using a shared variable, rather than using messages. Both threads will be able to safely read and write from it.
as mentioned you are flooding the client thread.
Try adding a sleep like this
Thread.sleep(dur!"msecs"(1500));
As mentioned by duselbaer and Anders S, in your example, the number of sends is huge, but the number of receives is limited by the sleep. So, when the thread should actually get a true, it is already preceded by an overwhelming number of falses in the queue.
Generally, if the child thread is able to receive faster than the parent thread sends, it's fine. Here is a working example produced from your code. The sleep calls may be substituted by doing some work, but the relation must generally hold.
import std.stdio;
import core.thread;
import std.concurrency;
import core.stdc.stdio;
extern (C) int kbhit();
void readSignal() {
for(int i = 0; ; i++) {
bool stop = receiveOnly!bool();
if(!stop)
writeln("reading signal... ", i);
else
{
writeln("stop reading signal...");
break;
}
Thread.getThis.sleep(1.msecs); // this should be no more than below
}
}
int main() {
auto reader = spawn(&readSignal);
bool stop = false;
while(!stop) {
if(kbhit()) {
stop = true;
}
send(reader, stop); // option 1
// reader.send(stop); // option 2 does the same thing as above via UFCS
Thread.getThis.sleep(1.msecs); // this should be no less than above
}
return 0;
}
I'm trying to write a simple thread pool program in pthread. However, it seems that pthread_cond_signal doesn't block, which creates a problem. For example, let's say I have a "producer-consumer" program:
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;
void * liberator(void * arg)
{
// XXX make sure he is ready to be freed
sleep(1);
pthread_mutex_lock(&my_cond_m);
pthread_cond_signal(&my_cond);
pthread_mutex_unlock(&my_cond_m);
return NULL;
}
int main()
{
pthread_t t1;
pthread_create(&t1, NULL, liberator, NULL);
// XXX Don't take too long to get ready. Otherwise I'll miss
// the wake up call forever
//sleep(3);
pthread_mutex_lock(&my_cond_m);
pthread_cond_wait(&my_cond, &my_cond_m);
pthread_mutex_unlock(&my_cond_m);
pthread_join(t1, NULL);
return 0;
}
As described in the two XXX marks, if I take away the sleep calls, then main() may stall because it has missed the wake up call from liberator(). Of course, sleep isn't a very robust way to ensure that either.
In real life situation, this would be a worker thread telling the manager thread that it is ready for work, or the manager thread announcing that new work is available.
How would you do this reliably in pthread?
Elaboration
#Borealid's answer kind of works, but his explanation of the problem could be better. I suggest anyone looking at this question to read the discussion in the comments to understand what's going on.
In particular, I myself would amend his answer and code example like this, to make this clearer. (Since Borealid's original answer, while compiled and worked, confused me a lot)
// In main
pthread_mutex_lock(&my_cond_m);
// If the flag is not set, it means liberator has not
// been run yet. I'll wait for him through pthread's signaling
// mechanism
// If it _is_ set, it means liberator has been run. I'll simply
// skip waiting since I've already synchronized. I don't need to
// use pthread's signaling mechanism
if(!flag) pthread_cond_wait(&my_cond, &my_cond_m);
pthread_mutex_unlock(&my_cond_m);
// In liberator thread
pthread_mutex_lock(&my_cond_m);
// Signal anyone who's sleeping. If no one is sleeping yet,
// they should check this flag which indicates I have already
// sent the signal. This is needed because pthread's signals
// is not like a message queue -- a sent signal is lost if
// nobody's waiting for a condition when it's sent.
// You can think of this flag as a "persistent" signal
flag = 1;
pthread_cond_signal(&my_cond);
pthread_mutex_unlock(&my_cond_m);
Use a synchronization variable.
In main:
pthread_mutex_lock(&my_cond_m);
while (!flag) {
pthread_cond_wait(&my_cond, &my_cond_m);
}
pthread_mutex_unlock(&my_cond_m);
In the thread:
pthread_mutex_lock(&my_cond_m);
flag = 1;
pthread_cond_broadcast(&my_cond);
pthread_mutex_unlock(&my_cond_m);
For a producer-consumer problem, this would be the consumer sleeping when the buffer is empty, and the producer sleeping when it is full. Remember to acquire the lock before accessing the global variable.
I found out the solution here. For me, the tricky bit to understand the problem is that:
Producers and consumers must be able to communicate both ways. Either way is not enough.
This two-way communication can be packed into one pthread condition.
To illustrate, the blog post mentioned above demonstrated that this is actually meaningful and desirable behavior:
pthread_mutex_lock(&cond_mutex);
pthread_cond_broadcast(&cond):
pthread_cond_wait(&cond, &cond_mutex);
pthread_mutex_unlock(&cond_mutex);
The idea is that if both the producers and consumers employ this logic, it will be safe for either of them to be sleeping first, since the each will be able to wake the other role up. Put it in another way, in a typical producer-consumer sceanrio -- if a consumer needs to sleep, it's because a producer needs to wake up, and vice versa. Packing this logic in a single pthread condition makes sense.
Of course, the above code has the unintended behavior that a worker thread will also wake up another sleeping worker thread when it actually just wants to wake the producer. This can be solved by a simple variable check as #Borealid suggested:
while(!work_available) pthread_cond_wait(&cond, &cond_mutex);
Upon a worker broadcast, all worker threads will be awaken, but one-by-one (because of the implicit mutex locking in pthread_cond_wait). Since one of the worker threads will consume the work (setting work_available back to false), when other worker threads awake and actually get to work, the work will be unavailable so the worker will sleep again.
Here's some commented code I tested, for anyone interested:
// gcc -Wall -pthread threads.c -lpthread
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t my_cond_m = PTHREAD_MUTEX_INITIALIZER;
int * next_work = NULL;
int all_work_done = 0;
void * worker(void * arg)
{
int * my_work = NULL;
while(!all_work_done)
{
pthread_mutex_lock(&my_cond_m);
if(next_work == NULL)
{
// Signal producer to give work
pthread_cond_broadcast(&my_cond);
// Wait for work to arrive
// It is wrapped in a while loop because the condition
// might be triggered by another worker thread intended
// to wake up the producer
while(!next_work && !all_work_done)
pthread_cond_wait(&my_cond, &my_cond_m);
}
// Work has arrived, cache it locally so producer can
// put in next work ASAP
my_work = next_work;
next_work = NULL;
pthread_mutex_unlock(&my_cond_m);
if(my_work)
{
printf("Worker %d consuming work: %d\n", (int)(pthread_self() % 100), *my_work);
free(my_work);
}
}
return NULL;
}
int * create_work()
{
int * ret = (int *)malloc(sizeof(int));
assert(ret);
*ret = rand() % 100;
return ret;
}
void * producer(void * arg)
{
int i;
for(i = 0; i < 10; i++)
{
pthread_mutex_lock(&my_cond_m);
while(next_work != NULL)
{
// There's still work, signal a worker to pick it up
pthread_cond_broadcast(&my_cond);
// Wait for work to be picked up
pthread_cond_wait(&my_cond, &my_cond_m);
}
// No work is available now, let's put work on the queue
next_work = create_work();
printf("Producer: Created work %d\n", *next_work);
pthread_mutex_unlock(&my_cond_m);
}
// Some workers might still be waiting, release them
pthread_cond_broadcast(&my_cond);
all_work_done = 1;
return NULL;
}
int main()
{
pthread_t t1, t2, t3, t4;
pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);
pthread_create(&t3, NULL, worker, NULL);
pthread_create(&t4, NULL, worker, NULL);
producer(NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
pthread_join(t4, NULL);
return 0;
}