如何在多线程应用程序中使用异步信号管理共享POSIX信号量

时间:2022-02-23 00:35:15

I've to write a thread-safe library that uses a POSIX semaphore (used as a mutex with initial value = 1) for sync. I found some problems to correctly manage async signals. I've an application that links against this static library and the application (multi-threaded) calls library's functions. Access to some internals structures are controlled by a posix semaphore (it's internal to the library):

我要编写一个线程安全的库,它使用POSIX信号量(用作初始值为1的互斥锁)进行同步。我发现了一些正确管理异步信号的问题。我有一个应用程序链接到这个静态库和应用程序(多线程)调用库的函数。对一些内部结构的访问由posix信号量控制(它是库的内部):

void library_func1(lib_handler *h)
{
   sem_wait(sem);
   /* do some stuff with global data */
   sem_post(sem);
}

void library_func2(lib_handler *h)
{
   sem_wait(sem);
   /* do some stuff with global data */
   sem_post(sem);
}

void library_close(lib_handler *h)
{
   ...
}

What append if an async signal, let's say SIGINT, is raised when one thread is locking the semaphore? If i relaunch the application i'll have a deadlock because the semaphore exists and it's value is 0. There is a function library_close that could release the semaphore when the async signal is raised but which is the best way to do and check this (I think that that function would be signal-safe only if followed by exit)? In multi-threaded application usually is a good practice having a single thread manager for all signals: this thread should be in the library or is ok to launch it in the application?

当一个线程锁定信号量时,如果异步信号(假设为SIGINT)被引发,会附加什么?如果我重新启动应用程序,我将有一个死锁,因为信号量存在,它的值为0.有一个函数library_close可以在异步信号被提出时释放信号量,但这是最好的方法和检查这个(我认为只有在退出后,该功能才是信号安全的)?在多线程应用程序中,通常一个好的做法是为所有信号都有一个单独的线程管理器:这个线程应该在库中,还是可以在应用程序中启动它?

Thank you all.

谢谢你们。

2 个解决方案

#1


0  

Linux futexes had the same problem. It is not fully solvable, but what you could do is write the pid of the process locking the semaphore somewhere in the same shared memory region. If another process tries to lock the semaphore and it is taking too long (for some value of 'too long'), it finds out what process has the semaphore locked by reading the pid from the shared memory. If that process no longer exists, you know you are in a deadlock (and you should probably just die since the library's internal data may be in an inconsistent state).

Linux futexes也有同样的问题。它不是完全可以解决的,但你可以做的是编写将信号量锁定在同一共享内存区域中某处的进程的pid。如果另一个进程试图锁定信号量并且它花费的时间太长(某些值为“太长”),它会通过从共享内存中读取pid来找出锁定信号量的进程。如果该进程不再存在,您就知道自己处于死锁状态(因为库的内部数据可能处于不一致状态,您可能应该死掉)。

There's still a small race with this as the process taking the lock may die just after locking but before writing its pid. AFAIK there's no way to avoid this using semaphores. (It might work if you have a lock implementation where the pid is written to the lock variable atomically on aquire, but you would probably need to write this yourself.)

由于采取锁定的过程可能在锁定之后但在写入其pid之前死亡,因此仍然存在一个小的竞争。 AFAIK使用信号量无法避免这种情况。 (如果你有一个锁实现,可能会有效,其中pid以原子方式写在aquire上,但你可能需要自己编写。)

#2


-1  

The state of a static library doesn't carry over between different runs of the app and isn't shared by other apps using it. it's part of the state of the application that's using it. So your semaphore won't be in a wonky state.

静态库的状态不会在应用程序的不同运行之间延续,并且不会被使用它的其他应用程序共享。它是使用它的应用程序状态的一部分。所以你的信号量不会处于不稳定的状态。

#1


0  

Linux futexes had the same problem. It is not fully solvable, but what you could do is write the pid of the process locking the semaphore somewhere in the same shared memory region. If another process tries to lock the semaphore and it is taking too long (for some value of 'too long'), it finds out what process has the semaphore locked by reading the pid from the shared memory. If that process no longer exists, you know you are in a deadlock (and you should probably just die since the library's internal data may be in an inconsistent state).

Linux futexes也有同样的问题。它不是完全可以解决的,但你可以做的是编写将信号量锁定在同一共享内存区域中某处的进程的pid。如果另一个进程试图锁定信号量并且它花费的时间太长(某些值为“太长”),它会通过从共享内存中读取pid来找出锁定信号量的进程。如果该进程不再存在,您就知道自己处于死锁状态(因为库的内部数据可能处于不一致状态,您可能应该死掉)。

There's still a small race with this as the process taking the lock may die just after locking but before writing its pid. AFAIK there's no way to avoid this using semaphores. (It might work if you have a lock implementation where the pid is written to the lock variable atomically on aquire, but you would probably need to write this yourself.)

由于采取锁定的过程可能在锁定之后但在写入其pid之前死亡,因此仍然存在一个小的竞争。 AFAIK使用信号量无法避免这种情况。 (如果你有一个锁实现,可能会有效,其中pid以原子方式写在aquire上,但你可能需要自己编写。)

#2


-1  

The state of a static library doesn't carry over between different runs of the app and isn't shared by other apps using it. it's part of the state of the application that's using it. So your semaphore won't be in a wonky state.

静态库的状态不会在应用程序的不同运行之间延续,并且不会被使用它的其他应用程序共享。它是使用它的应用程序状态的一部分。所以你的信号量不会处于不稳定的状态。