IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Le noyau UNIX de MAC OS X est-il buggé ?


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut Le noyau UNIX de MAC OS X est-il buggé ?
    Bonjour,

    Ci-dessous, deux fonctions. GetBSDProcessList récupère la liste des processus (fonction trouvée sur le site d'Apple), et fonction CExeRunning écrite par mes soins qui permet de savoir si un process est en cours d'exécution, c'est à dire s'il se trouve dans la liste créée par GetBSDProcessList.

    Et bien ce code ne fonctionne pas. Alors je ne suis pas très habitué à programmer en C, donc j'en appelle à vos compétences car là j'avoue que je ne vois pa où ça coince à part peut-être au niveau du noyau lui-même... je m'explique :

    J'ai un processus A et un processus B qui tournent. A est un processus de contrôle (un daemon pour info) qui vérifie que B tourne en permanence.

    A appelle donc CExeRunning('B', 0) à intervalle régulier pour savoir si B est en cours d'exécution, et le cas échéant relance B.

    Si je lance A seul, il détecte que B ne tourne pas et le lance, puis détecte bien ensuite que B est lancé et ne fait plus rien : Ok
    Si je lance B puis A, A détecte que B tourne déjà et ne fait rien : Ok
    Si je "kill" B en ayant lancé B puis A, A détecte que B ne tourne plus et relance B: Ok
    Si je "kill" B alors qu'il a été lancé par A, A ne voit rien, c'est à dire que B ne tourne plus, mais qu'il se trouve apparemment toujours dans la liste de processus renvoyée par GetBSDProcessList (écrite chez Apple je le rappelle).

    En clair: B ne détecte que A ne tourne pas uniquement si A n'est pas parent de B...

    Je ne suis pas programmeur C/Mac mais Pascal/Win32 et j'avoue que cette plateforme Mac commence à sérieusement me ... au point d'ailleurs que je suis obligé de faire du C car certaines fonctions ne sont pas raisonnablement faisables en Pascal. Bref, j'ai peut-être fait une erreur quelque part sur les pointeurs dans CExeRunning par ignorance. J'aimerais que ce soit le cas. Hélas, je ne vois vraiment pas où.

    Merci d'avance pour votre aide,
    André.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
     
    static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
    // Returns a list of all BSD processes on the system.  This routine
    // allocates the list and puts it in *procList and a count of the
    // number of entries in *procCount.  You are responsible for freeing
    // this list (use "free" from System framework).
    // On success, the function returns 0.
    // On error, the function returns a BSD errno value.
    {
        int                 err;
        kinfo_proc *        result;
        bool                done;
        static const int    name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
        // Declaring name as const requires us to cast it when passing it to
        // sysctl because the prototype doesn't include the const modifier.
        size_t              length;
     
        assert( procList != NULL);
        assert(*procList == NULL);
        assert(procCount != NULL);
     
        *procCount = 0;
     
        // We start by calling sysctl with result == NULL and length == 0.
        // That will succeed, and set length to the appropriate length.
        // We then allocate a buffer of that size and call sysctl again
        // with that buffer.  If that succeeds, we're done.  If that fails
        // with ENOMEM, we have to throw away our buffer and loop.  Note
        // that the loop causes use to call sysctl with NULL again; this
        // is necessary because the ENOMEM failure case sets length to
        // the amount of data returned, not the amount of data that
        // could have been returned.
     
        result = NULL;
        done = false;
        do {
            assert(result == NULL);
     
            // Call sysctl with a NULL buffer.
     
            length = 0;
            err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
    					 NULL, &length,
    					 NULL, 0);
            if (err == -1) {
                err = errno;
            }
     
            // Allocate an appropriately sized buffer based on the results
            // from the previous call.
     
            if (err == 0) {
                result = (kinfo_proc*)malloc(length);
                if (result == NULL) {
                    err = ENOMEM;
                }
            }
     
    		// Call sysctl again with the new buffer.  If we get an ENOMEM
            // error, toss away our buffer and start again.
     
            if (err == 0) {
                err = sysctl( (int *) name, (sizeof(name) / sizeof(*name)) - 1,
    						 result, &length,
    						 NULL, 0);
                if (err == -1) {
                    err = errno;
                }
                if (err == 0) {
                    done = true;
                } else if (err == ENOMEM) {
                    assert(result != NULL);
                    free(result);
                    result = NULL;
                    err = 0;
                }
            }
        } while (err == 0 && ! done);
     
        // Clean up and establish post conditions.
     
        if (err != 0 && result != NULL) {
            free(result);
            result = NULL;
        }
        *procList = result;
        if (err == 0) {
            *procCount = length / sizeof(kinfo_proc);
        }
     
        assert( (err == 0) == (*procList != NULL) );
     
    	return err;
    }
     
    int CExeRunning(char * NomApplication, int StopProcess)
    {
    	kinfo_proc * process;
    	int err, i, res, j, l;
    	size_t             processCount;
    	ProcessSerialNumber * ProcessNum;
    	pid_t v_pid;
     
    	process = NULL;
    	processCount = 0;
    	res = 0;
    	err = GetBSDProcessList(&process, &processCount);
    	for (i=0; i< processCount; i++) {
    		if (strcmp(process[i].kp_proc.p_comm, NomApplication) == 0 ) {
    			if (StopProcess != 0) {
    				v_pid = process[i].kp_proc.p_pid;
    				ProcessNum = (ProcessSerialNumber*)malloc(sizeof(ProcessSerialNumber));
    				GetProcessForPID(v_pid, ProcessNum);
    				KillProcess(ProcessNum);
    				free(ProcessNum);
    			}
    			res = 1;
    		}
    	}		
    	free(process);
    	return res;
    }

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 094
    Billets dans le blog
    146
    Par défaut
    Bonjour,

    Malheureusement je n'ai pas compris tout le code.
    ( Une petite remarque en passant -> Vous avez des noms de variable en français dans un code qui semble très anglais :p )

    Sinon, j'aimerais savoir comment vous relancer le processus ( utilisation de quel commande ).
    De plus, dans votre code de 'CExeRunning' il y a un code pour tuer un processus ... je n'ai pas saisi le pourquoi ...
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Bonjour,

    Alors d'abord pour GetBSDProcessList, c'est du code trouvé sur le site d'Apple. Il remplit simplement une structure de type kinfo_proc (via appel à sysctl, fonction du noyau BSD de Mac OS X), qui contient toutes les informations (beaucoup trop !) sur chaque processus. Les infos qui m'intéressent sont uniquement le pid et le nom du process, soit respectivement les champs kp_proc.p_pid et kp_proc.p_comm. Je suppose que cette fonction ne pose pas de problème puisque fournie par Apple...

    Ma fonction, elle, est très simple: Elle parcours la structure de type kinfo_proc remplie précédemment pour trouver un processus dont le nom correspond. Si trouvé, elle renvoie 1, sinon 0.

    Pourquoi y-a-t-il de quoi killer le process ? Simplement parce que dans certains cas (lors du débogage en fait), je veux non seulement savoir si le process existe, mais aussi le terminer, c'est tout.

    Pour relancer mon process B depuis mon processus A, j'utilise quelque chose comme TProcess avec un appel à la méthode Process.Create je crois, enfin quelque chose de très standard (désolé, je suis en déplacement et je n'ai pas le code sous les yeux, donc de mémoire...).

    André.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 094
    Billets dans le blog
    146
    Par défaut
    Citation Envoyé par sinfoni Voir le message
    Pour relancer mon process B depuis mon processus A, j'utilise quelque chose comme TProcess avec un appel à la méthode Process.Create je crois, enfin quelque chose de très standard (désolé, je suis en déplacement et je n'ai pas le code sous les yeux, donc de mémoire...).
    Puis je avoir une doc la dessus ... car je n'ai trouvé qu'un truc en pascal actuellement ...
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    La doc est ici: http://lazarus-ccr.sourceforge.net/d.../tprocess.html

    Et voici le code de ma fonction (en Pascal cette fois !):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    // Fonction qui reproduit le ShellExecute de Windows
    Function ShellExecute(nul: ShortInt; Action: String; Filename: String; Param: String; Dir: String; Mode: Integer): Integer;  // OK
     
    var AProcess : TProcess;
    Begin
        result := 0;
           try
               AProcess := TProcess.Create(nil);
               AProcess.CommandLine := Filename + ' ' + Param;
               If Mode = SW_WAIT then AProcess.Options :=  AProcess.Options + [poWaitOnExit];
               AProcess.Execute;
               result := 33;
           Finally
               AProcess.Free;
           end;
    end;
    S'agissant du portage de Win32 vers Mac OS, j'ai conservé les mêmes paramètres que la fonction ShellExecute Win32 bien que tous ne soient pas utilisés ici (Ex: la notion de répertoire de travail n'existe pas sur Mac OS X). Le but est bien sûr de conserver le code le plus proche possible entre la plateforme Win32 et Mac OS X.

    André.

  6. #6
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Hypothese: ton process est devenu un zombie parce que personne ne fait de wait dessus. (Si tu veux programmer sous Unix -- et MacOS c'est Unix pour pas mal de choses --, le premier bouquin a te procurer et a comprendre, c'est Advanced Programming in the UNIX Environment de W.R. Stevens)

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Mon process B est killé, il ne tourne plus du tout (j'utilise par exemple le gestionnaire de tâches du Mac). Il n'apparait plus dans la liste des process du Mac, il n'apparait plus non plus dans la liste des process affichables via la commande TOP dans le terminal.
    Il n'y a plus guère que le process A (le père) qui voit le process B (son fils). Si je relance une autre instance du programme A, cette nouvelle instance, elle, voit bien que le process B ne tourne pas. C'est ce qui est étrange. J'ai fait d'autres tests:

    Au lieu de lancer le processus B via la méthode précédemment décrite, j'en fait un daemon et j'utilise lanchctl (mais toujours depuis le programme A via un appelle "fpsystem"). Dans ce cas, il me semble que le père du processus lancé n'est plus A, mais le process launchd. Et bien là pas de souci : Si je kill B, A vois que B est arrêté, le relance B (toujours via launchctl), et je peux rekiller, A relance et ainsi de suite...

    Je ne sais pas ce qu'est un process "zombie", mais si c'en était un, je suppose que tous les autres process le verraient ainsi. Or ce n'est pas le cas puisque seul A est affecté...

    André.

    André.

  8. #8
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Un zombie est un process qui est mort mais dont le noyau garde encore une partie des information parce que le pere n'a pas encore fait un wait() dessus. Les zombies sont souvent filtres par les programmes listant les processus sauf si on les demande explicitement (ps ax, ps -e)

    Malgre le fait que ca ne corresponde pas avec le fait qu'une nouvelle instance de A ne le detecte pas, tous les autres symptomes correspondent. Quelque chose de ce genre -- avec peut-etre une specificite de MacOS -- semble donc etre la piste la plus probable. Bien plus probable qu'un bug dans la gestion des processus.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Je testerai le listage avec ps -e demain ou mercredi.

    PS: Pour le titre, l'idée était avant tout de susciter l'intérêt... je trouverais l'existence d'un tel bug plus que surprenante.
    Toutefois, comme pour tout OS, et Unix ne fait pas exception, des bugs, il y en a. J'ai notemment vu un bug sur sysctl dans BSD 4 et.... c'est une des fonctions utilisées justement.

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    147
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Mars 2006
    Messages : 147
    Par défaut
    Pour conclure: Point de processus zombie...

Discussions similaires

  1. Noyau Linux: La version 3.17 est disponible
    Par Amine Horseman dans le forum Linux
    Réponses: 4
    Dernier message: 07/10/2014, 18h06
  2. [AJAX] Ajax et unix et mac
    Par polopbob dans le forum AJAX
    Réponses: 1
    Dernier message: 08/11/2011, 09h41
  3. Réponses: 5
    Dernier message: 25/03/2003, 17h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo