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;
}