Я пишу программу, которая использует общую память и семафоры для ipc. Существует один основной процесс сервера, который создает общую память и семафоры. Любое количество клиентских процессов может подключаться к общей памяти и читать и записывать в нее, когда это разрешено. Семафоры предоставляют механизм блокировки для управления чтением и записью. Все работает нормально, кроме случаев, когда я пытаюсь завершить работу клиента. Блок семафоров для доступа к разделяемой памяти находится в потоке, и по завершении процесса у меня нет возможности освободить блок семафоров, поэтому поток завершается правильно. Как бы я пошел по этому поводу? Это для Linux.
Если быть точным, то есть один шм и два сема. Первый sem блокирует запись, а второй блокирует чтение. Когда клиенту есть что написать, он ожидает, что sem записи будет равен 0, затем устанавливает его в 1, пишет, затем устанавливает значение sem для чтения в 0, что освобождает ожидающий сервер, чтобы прочитать то, что написал клиент. после чтения сервер устанавливает запись в 0 и следующий клиент в строке получает возможность записи. Он зависает при вызове semop, который сбрасывается, когда read sem равен 0. Этот вызов semop находится в потоке, и мне нужно выяснить, как правильно выйти из этого потока, прежде чем позволить завершить основной поток.
Вот пример того, что я хочу сделать, но не работает (сон выдает себя за зависший вызов semop):
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void termination_handler (int signum) {
printf( "Got Signal\n" );
}
void *threadfunc( void *parm ) {
struct sigaction action;
action.sa_handler = termination_handler;
sigemptyset( &action.sa_mask );
action.sa_flags = 0;
sigaction( SIGUSR1, &action, NULL );
printf("Thread executing\n");
sleep( 100 ); // pretending to be the semaphore
pthread_exit( NULL );
}
int main() {
int status;
pthread_t threadid;
int thread_stat;
status = pthread_create( &threadid, NULL, threadfunc, NULL );
if ( status < 0) {
perror("pthread_create failed");
exit(1);
}
sleep( 5 );
status = pthread_kill( threadid, SIGUSR1 );
if ( status < 0 )
perror("pthread_kill failed");
status = pthread_join( threadid, (void *)&thread_stat );
if ( status < 0 )
perror("pthread_join failed");
exit( 0 );
}