简体   繁体   English

posix sem_post无法唤醒sem_wait,其中sem初始化在线程中。 linux

[英]posix sem_post can't wake sem_wait where the sem init in thread. linux

This is a strange problem.I init sem and destory it first,then i init it again in a thread.then, i can't wake it again.the code is: 这是一个奇怪的问题。我先初始化sem并对其进行销毁,然后再在线程中对其进行初始化。然后,我无法再次唤醒它。代码为:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <pthread.h>

sem_t sem;
int key = 1;

static void *
wait_func()
{
    printf("i'm wait\n");
    sem_wait(&sem);
}

static void *
cancel_func(void *arg)
{
    pthread_t tid = *(pthread_t *)arg;
    if (key == 1)
    {
        sleep(1);
        key = 0;
    }
    else
        sleep(3);
    if(pthread_cancel(tid) == 0)
        printf("cancle!\n");

    sem_init(&sem, 0, 0);
    sem_destroy(&sem);
}

int
main(int argc, char *argv[])
{
    pthread_t wthread, cthread;
    pthread_attr_t attr;
    int i = 0;

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    sem_init(&sem, 0, 0);

    while (i < 2)
    {
    //        sem_init(&sem, 0, 0);

        pthread_create(&wthread, &attr, wait_func, NULL);
        if (i < 1)
            pthread_create(&cthread, &attr, cancel_func, &wthread);
        if (key == 0)
        {
            sleep(2);
            if (sem_post(&sem) == 0)
                printf("post!\n");
            key = 1;
        }
        sleep(4);
        ++i;
    }
    sleep(1000);
}

however,it will be work that changed sem_init in while loop like comment!So i have straced two program,and finded 1)init in thread,sem_post didn't call sys_futex,like this: 但是,这将像在注释中那样在while循环中更改sem_init的工作!所以我建立了两个程序,并找到1)线程中的init,sem_post没有调用sys_futex,如下所示:

nanosleep({2, 0}, i'm wait

{2, 0}) = 0 write(1, "post!\\n", 6post! ) = 6 {2,0})= 0 write(1,“ post!\\ n”,6post!)= 6

2)init in main process,sem_post call sys_futex,like this: 2)在主进程中初始化,sem_post调用sys_futex,如下所示:

nanosleep({2, 0}, i'm wait

{2, 0}) = 0 futex(0x600dc0, FUTEX_WAKE_PRIVATE, 1) = 1 write(1, "post!\\n", 6post! ) = 6 {2,0})= 0 futex(0x600dc0,FUTEX_WAKE_PRIVATE,1)= 1写(1,“ post!\\ n”,6post!)= 6

Then,i thought maybe this is a problem with syscall.I have used gdb to disassemble two program in sem_post. 然后,我以为这可能是syscall的问题。我用gdb拆装了sem_post中的两个程序。 unfortunately,1)init in thread,it also call syscall in sem_post;2) compared their registry status where rip is syscall,same too. 不幸的是,1)在线程中初始化,它还在sem_post中调用syscall; 2)比较了rip是syscall的注册表状态,也是如此。

in thread:
rax            0xca     202          //sys_futex
rbx            0x3c0e61bbc0     257939323840
rcx            0x0      0            //utime
rdx            0x1      1            //val
rsi            0x81     129          //op:private_wake
rdi            0x600dc0 6294976      //sem uaddr
in main process:
rax            0xca     202
rbx            0x3c0e61bbc0     257939323840
rcx            0x0      0
rdx            0x1      1
rsi            0x81     129
rdi            0x600da0 6294944

At last,i have no idea about this problem.Please give me some advise to find out the solution,thanks. 最后,我对这个问题一无所知。谢谢,请给我一些建议以找出解决方案。

I think that your problem lies in the access to key . 我认为您的问题在于对key的访问。 There is no guarantee that the access to shared variables is atomic. 不能保证对共享变量的访问是原子的。 In particular the compiler might optimize the reading of a value from memory, such that it doesn't see a modification of the value that is done in another thread. 特别是,编译器可能会优化从内存中读取值的过程,从而不会看到在另一个线程中完成的值修改。

To avoid that the optimizer kicks in, you'd have to declare your key variable volatile . 为了避免优化程序启动,您必须声明key变量volatile But I am not sure that the way you have written your program would guarantee that there are memory barriers that would guarantee that the threads are guaranteed to seen modifications and that the concurrent write is not mixing things up. 但我不知道,你已经写你的程序将保证有问题,保证线程都保证看到的修改并行写记忆障碍的方式不混合的东西了。

Modern C11 also has _Atomic to ensure that the access is atomic. 现代C11还具有_Atomic以确保访问是原子的。 But C11 is not yet fully implemented (there may be some compilers that have that feature). 但是C11尚未完全实现(可能有些编译器具有该功能)。 If it would be, there would be a problem with semaphores, since C11 only has mutexes and not semaphores as lock structures. 如果是这样,则信号量会出现问题,因为C11仅具有互斥量,而没有信号量作为锁定结构。 How these two features would cooperate is not specified, yet. 这两个功能如何协同工作尚未确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM