Comment puis-je arrêter un thread est en attente d'un sémaphore de l'opération
Je suis en train d'écrire un programme qui utilise la mémoire partagée et les sémaphores ipc. Il y a un processus serveur principal qui crée de la mémoire partagée et les sémaphores. Un nombre quelconque de processus client peut s'attacher à la mémoire partagée et les lire et à écrire, lorsque cela est autorisé. Les sémaphores de fournir le mécanisme de blocage de contrôler les lectures et les écritures. Tout fonctionne bien sauf lorsque je tente de mettre fin à un client. Le sémaphore de bloquer les accès à la mémoire partagée est dans un thread et sur le processus de résiliation, je n'ai aucun moyen de libérer le sémaphore bloc de sorte que le thread s'arrête correctement. Comment pourrais-je aller à ce sujet? C'est pour Linux.
Pour être précis, il y a une shm et deux sems. La première sem blocs d'écriture, et le second bloque la lecture. Lorsqu'un client a quelque chose à écrire, il attend l'écriture sem à 0, alors il définit à 1, écrit, puis définit le lire sem à 0, ce qui libère l'attente du serveur de lire ce que le client l'a écrit. une fois lu le serveur définit l'écriture, à la sem à 0 et que le prochain client en ligne est à écrire. Il se bloque sur une semop appel qui se libère lors de la lecture sem est de 0. Cette semop appel est dans un thread et j'ai besoin de comprendre comment sortir de ce thread correctement avant de laisser le thread principal de résilier.
Voici un exemple de ce que je veux faire, mais ne fonctionne pas (le sommeil se fait passer pour la pendaison de semop appel):
#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 );
}
Donc, en mettant de côté le fil-kill question, la vraie question est pourquoi vous bloquer si longue attente sur le partage de l'accès à la mémoire. Vraisemblablement, les clients sont en attente sur le serveur pour configurer l'écriture sem retour à l'endroit où ils peuvent débloquer. Est serveur exécutant certaines tâches ou est-il possible qu'il y ait quelques cas non diagnostiqués de blocage des problèmes avec le design?
eh bien, à élaborer d'autres. il n'y a pas de problème avec la logique ou de la période d'attente. chaque client possède également une shm qui se bloque jusqu'à ce que le serveur écrit quelque chose à ce processus shm, et le serveur a une shm qui se bloque jusqu'à ce qu'un client écrit quelque chose pour que les processus de la shm. de sorte que vous pouvez le voir, lorsque rien ne se passe, tous les clients et le serveur vient de s'asseoir et d'attendre. Je suis en fait enquête à l'aide de stdin ou de la mémoire des files d'attente à la place. Cette méthode originale semble être trop compliqué par rapport à celles d'autres méthodes.
Ah, l'intrigue s'épaissit. 🙂 FWIW, je pense que la shm est un pain PITA pour rien au-delà la plupart du temps à des tâches critiques et dans ce cas, vous êtes en attente d'un lot. Si vous avez le luxe de recodage, Posix MQs sembler comme un bon choix ici. Chaque côté peut écrire leurs données dans une file d'attente sans blocage et ils peuvent utiliser quelque chose comme mq_notify() sur le côté lecture. Sans knowning les détails de l'application (et je soupçonne qu'il y a de plus), il simplifie un certain nombre de choses.
je pense que je suis fait pour y aller avec de la pipe et de s'occuper uniquement de la norme de descripteurs de fichiers. Joué avec lui et il fait le travail et le bien, et est parfaitement simple. Merci pour toute l'aide et l'entrée. Si vous avez des objections à pipe laissez-moi savoir, j'espère que c'est la dernière fois que j'ai recoder cette!
OriginalL'auteur user19745 | 2009-07-17
Vous devez vous connecter pour publier un commentaire.
Dit-il, c'est pour Linux.
Il serait utile si vous pouviez dire exactement comment le faire. Je suppose que vous êtes de blocage dans sem_wait ou sem_timedwait. Si votre fil bloque et que vous souhaitez l'interrompre, vous pouvez utiliser pthread_kill.
Bien sûr, vous devez mettre en place le bon gestionnaire de signal (homme sigaction) pour attraper SIGUSR1 et vous avez besoin de vérifier le code de retour de sem_wait() pour EINTR, dans ce cas, vous pouvez faire ce que vous voulez faire savoir que vous avez été interrompue et n'a pas obtenu la serrure.
Dans le cas où vous êtes en utilisant des procédés, vous utilisez simplement tuer() et ne pas pthread_kill() de fournir l'id de processus. (désolé, j'ai d'abord mal lu et pensé que vous étiez à l'aide de threads)
semop()
plutôt quesem_wait()
et amis.OriginalL'auteur Moises Silva
J'en ai deux et un demi-réponses pour vous. 🙂
Tout d'abord, votre exemple de code qui fonctionne pour moi (sur Linux): le pthread_kill avec succès
EINTR
upts le thread de travail est sommeil comme prévu après environ cinq secondes, comme l'a révélé avec un peu de printfs et de se souvenir de la valeur de retour de sommeil. AFAICT, si vous voulez le signal d'interrompre un thread spécifique, vous l'avez fait.Ensuite, essayez de
SEM_UNDO
. Cet indicateur peut être défini dans le sem_flg membre passée dans le sembuf argument semop, et il sera, comme son nom l'indique, annuler sémaphore ajustements à la fin du processus. IIUC, lorsque vous tuez un client, que le client laisse un sémaphore de façon inappropriée verrouillé.SEM_UNDO
était fabriqué pour cette circonstance.Enfin et de façon respectueuse, vous avez peut-être inversé la logique de sémaphores ici? Comme je l'ai lu votre question, un semval de zéro indique que "ressource libre" et un semval de l'un est la "ressource verrouillée" (citation: "...[client] attend pour l'écriture, à la sem à 0, alors il définit à 1, écrit..."). Toutefois, si deux ou plus de deux écrit des clients sont en attente pour un SysV sem à tomber à zéro, ils vont tous être libérés ensemble lorsque cela se produit. C'est plutôt une mauvaise condition de course, ce qui pourrait à tout le moins la conséquence imprévue de sémaphore diminutions et les augmentations.
Ah, je n'en connaît qu'un seul
semop()
effectué "en attente de zéro" et "post". (Avez-vous une exemple de code quelque part?) Oui, ça va, même si j'avoue que je trouve cette utilisation un peu maladroit. Merci.OriginalL'auteur pilcrow
Fonction de votre environnement, vous pourriez peut-être essayer de prendre le sémaphore avec un délai d'attente. Après chaque délai d'attente de vérifier si un proche thread a été demandé et tout simplement abandonner et à l'arrêt.
OriginalL'auteur Spence
Il peut ne pas être la meilleure idée pour utiliser le blocage de mutex/sémaphores si les opérations sur l'aire protégée peut durer trop longtemps à vos fins.
Vous pouvez résoudre le problème en mettant de lire et d'écrire des requêtes à une file d'attente (liste liée, par exemple) et laissez-le premier dans la file d'attente pour fonctionner sur l'aire protégée et supprimer de la liste une fois qu'il pénètre dans la zone.
En cas de lecture seule op, vous pouvez accéder à d'autres lectures entrer dans la zone protégée ainsi aussi longtemps que la première opération est en lecture seule. Lors de la première opération est d'écrire, de l'aire protégée doit être vide avant d'autoriser l'accès.
Liste des modifications doivent être protégés par des mutex (ou quelque chose de semblable), mais qui est près de la constante de temps et vous avez probablement en mesure de payer.
Quand les fils sont assis dans une file d'attente, chacun a sa propre variable de condition que vous pouvez utiliser pour réveiller l'un d'eux. La variable de Condition doit être protégée par un mutex. Vous pouvez stocker la variable de condition, mutex, etc ... dans une structure et mettez les dans un tableau ou d'une liste et de stocker l'id de thread avec chaque sorte qu'il sera facile de trouver le fil que vous voulez réveiller.
Une fois que le thread se réveille, il vérifie d'abord ce qui était la raison pour laquelle il a dû se réveiller. Si la sortie indicateur est défini, alors le thread savoir à la sortie.
OriginalL'auteur vraa