Skip to content

Commit 88a1c86

Browse files
author
Charles PIGNEROL
committed
Version 6.13.0 of 03/14/25. Possibility of delegating to the Process class the destruction of processes at the end of software execution.
1 parent b234fb1 commit 88a1c86

File tree

5 files changed

+123
-22
lines changed

5 files changed

+123
-22
lines changed

cmake/version.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#
44

55
set (TK_UTIL_MAJOR_VERSION "6")
6-
set (TK_UTIL_MINOR_VERSION "12")
7-
set (TK_UTIL_RELEASE_VERSION "1")
6+
set (TK_UTIL_MINOR_VERSION "13")
7+
set (TK_UTIL_RELEASE_VERSION "0")
88
set (TK_UTIL_VERSION ${TK_UTIL_MAJOR_VERSION}.${TK_UTIL_MINOR_VERSION}.${TK_UTIL_RELEASE_VERSION})
99

1010
set (TK_UTIL_SCRIPTING_MAJOR_VERSION ${TK_UTIL_MAJOR_VERSION})

src/TkUtil/ApplicationStats.cpp

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "TkUtil/Exception.h"
44
#include "TkUtil/File.h"
55
#include "TkUtil/NumericConversions.h"
6+
#include "TkUtil/Process.h"
67
#include "TkUtil/UTF8String.h"
78

89
#include <TkUtil/Date.h>
@@ -62,30 +63,38 @@ string ApplicationStats::getFileName (const string& appName, const string& logDi
6263

6364
void ApplicationStats::logUsage (const string& appName, const string& logDir)
6465
{
65-
// En vue de ne pas altérer le comportement de l'application tout est effectuée dans un processus fils.
66-
// Par ailleurs on quitte le processus fils par return et non exit pour passer dans le destructeur des variables automatiques créées (TermAutoStyle, ...).
66+
// En vue de ne pas altérer le comportement de l'application tout est effectuée dans un processus fils => exit (0) en toutes circonstances.
6767
errno = 0;
6868
const pid_t pid = fork ( );
6969
if ((pid_t)-1 == pid)
7070
{
71+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
7172
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : échec de fork : " << strerror (errno) << co_endl;
7273
return;
7374
} // if ((pid_t)-1 == pid)
7475
if (0 != pid)
76+
{
77+
Process::killAtEnd (pid);
7578
return; // Parent
79+
}
7680

7781
// On détache complètement le fils du parent => peut importe qui fini en premier, l'autre ira jusqu'au bout :
7882
const pid_t sid = setsid ( );
7983
if ((pid_t)-1 == sid)
8084
{
81-
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : échec de setsid : " << strerror (errno) << co_endl;
85+
{
86+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
87+
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : échec de setsid : " << strerror (errno) << co_endl;
88+
}
8289
exit (0);
8390
} // if ((pid_t)-1 == sid)
8491

85-
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
8692
if ((true == appName.empty ( )) || (true == logDir.empty ( )))
8793
{
88-
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : nom d'application ou répertoire des logs non renseigné (" << appName << "/" << logDir << ")." << co_endl;
94+
{
95+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
96+
ConsoleOutput::cerr ( ) << "ApplicationStats::logUsage : nom d'application ou répertoire des logs non renseigné (" << appName << "/" << logDir << ")." << co_endl;
97+
}
8998
exit (0);
9099
} // if ((true == appName.empty ( )) || (true == logDir.empty ( )))
91100

@@ -105,26 +114,38 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
105114
File dir (logDir);
106115
if ((false == dir.exists ( )) || (false == dir.isDirectory ( )) || (false == dir.isExecutable ( )) || (false == dir.isWritable ( )))
107116
{
108-
ConsoleOutput::cerr ( ) << "Erreur, " << logDir << " n'est pas un répertoire existant avec les droits en écriture pour vous." << co_endl;
117+
{
118+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
119+
ConsoleOutput::cerr ( ) << "Erreur, " << logDir << " n'est pas un répertoire existant avec les droits en écriture pour vous." << co_endl;
120+
}
109121
exit (0);
110122
} // if ((false == dir.exists ( )) || (false == dir.isDirectory ( )) || ...
111123
File logFile (fileName.utf8 ( ));
112124
if (false == logFile.isWritable ( ))
113125
{
114-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : absence de droits en écriture." << co_endl;
126+
{
127+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
128+
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : absence de droits en écriture." << co_endl;
129+
}
115130
exit (0);
116131
} // if (false == logFile.isWritable ( ))
117132
}
118133
catch (const Exception& exc)
119134
{
120-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : " << exc.getFullMessage ( ) << co_endl;
135+
{
136+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
137+
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : " << exc.getFullMessage ( ) << co_endl;
138+
}
121139
exit (0);
122140
}
123141
catch (...)
124142
{
125143
}
126144

127-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : erreur non documentée." << co_endl;
145+
{
146+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
147+
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << " : erreur non documentée." << co_endl;
148+
}
128149

129150
exit (0);
130151
} // if (NULL == file)
@@ -133,15 +154,21 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
133154
int fd = fileno (file);
134155
if (-1 == fd)
135156
{
136-
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << co_endl;
157+
{
158+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
159+
ConsoleOutput::cerr ( ) << "Erreur lors de l'ouverture du fichier de logs " << fileName << co_endl;
160+
}
137161
exit (0);
138162
} // if (-1 == fd)
139163

140164
// Appliquer un verrou exclusif sur le fichier de logs :
141165
errno = 0;
142166
if (0 != flock (fd, LOCK_EX))
143167
{
144-
ConsoleOutput::cerr ( ) << "Erreur lors du verrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
168+
{
169+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
170+
ConsoleOutput::cerr ( ) << "Erreur lors du verrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
171+
}
145172
fclose (file);
146173
exit (0);
147174
} // if (0 != flock (fd, LOCK_EX))
@@ -151,7 +178,10 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
151178
{
152179
if (0 != fchmod (fd, S_IRWXU | S_IRWXG | S_IRWXO))
153180
{
154-
ConsoleOutput::cerr ( ) << "Erreur lors du confèrement à autrui des droits en écriture sur le fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
181+
{
182+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
183+
ConsoleOutput::cerr ( ) << "Erreur lors du confèrement à autrui des droits en écriture sur le fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
184+
}
155185
fclose (file);
156186
exit (0);
157187

@@ -178,13 +208,19 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
178208
} // while (2 == fscanf (file, "%s\t%u", name, &count))
179209
if (0 != errno)
180210
{
181-
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : " << strerror (errno) << co_endl;
211+
{
212+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
213+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : " << strerror (errno) << co_endl;
214+
}
182215
fclose (file);
183216
exit (0);
184217
} // if (0 != errno)
185218
else if ((flag < 2) && (EOF != flag))
186219
{
187-
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : fichier probablement corrompu." << co_endl;
220+
{
221+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
222+
ConsoleOutput::cerr ( ) << "Erreur lors de la lecture du fichier de logs " << fileName << " en ligne " << (unsigned long)line << " : fichier probablement corrompu." << co_endl;
223+
}
188224
fclose (file);
189225
exit (0);
190226
} // if (flag < 2)
@@ -195,7 +231,10 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
195231
errno = 0;
196232
if (0 != fseek (file, 0, SEEK_SET))
197233
{
198-
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
234+
{
235+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
236+
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
237+
}
199238
fclose (file);
200239
exit (0);
201240
} // if (0 != fseek (file, 0, SEEK_SET))
@@ -204,24 +243,33 @@ void ApplicationStats::logUsage (const string& appName, const string& logDir)
204243
{
205244
if (fprintf (file, "%s\t%u\n", (*itl).first.c_str ( ), (*itl).second) < 0)
206245
{
207-
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << "."<< co_endl;
246+
{
247+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
248+
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << "."<< co_endl;
249+
}
208250
fclose (file);
209251
exit (0);
210252
}
211253
} // for (map<string, size_t>::const_iterator itl = logs.begin ( ); logs.end ( ) != itl; itl++)
212254
errno = 0;
213255
if (0 != fflush (file))
214256
{
257+
{
258+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
215259
ConsoleOutput::cerr ( ) << "Erreur lors de la réécriture du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
216-
fclose (file);
217-
exit (0);
260+
}
261+
fclose (file);
262+
exit (0);
218263
} // if (0 != fflush (file))
219264

220265
// Libération du verrou :
221266
errno = 0;
222267
if (0 != flock (fd, LOCK_UN))
223268
{
224-
ConsoleOutput::cerr ( ) << "Erreur lors du déverrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
269+
{
270+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
271+
ConsoleOutput::cerr ( ) << "Erreur lors du déverrouillage du fichier de logs " << fileName << " : " << strerror (errno) << co_endl;
272+
}
225273
fclose (file);
226274
} // if (0 != flock (fd, LOCK_UN))
227275

src/TkUtil/Process.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "TkUtil/AnsiEscapeCodes.h"
12
#include "TkUtil/Process.h"
23
#include "TkUtil/File.h"
34
#include "TkUtil/UTF8String.h"
@@ -80,6 +81,7 @@ const vector<string>& Process::ProcessOptions::getOptions ( ) const
8081
// ===========================================================================
8182

8283
vector<Process*> Process::_tasks;
84+
set<pid_t> Process::_toKill;
8385
int Process::_argc = 0;
8486
char** Process::_argv = 0;
8587
char** Process::_envp = 0;
@@ -444,6 +446,28 @@ void Process::initialize (char* envp [])
444446
} // Process::initialize
445447

446448

449+
void Process::finalize ( )
450+
{
451+
for (set<pid_t>::iterator itk = _toKill.begin ( ); _toKill.end ( ) != itk; itk++)
452+
{
453+
int res = ::kill (*itk, SIGKILL);
454+
if (0 != res)
455+
{
456+
TermAutoStyle as (cerr, AnsiEscapeCodes::blueFg);
457+
ConsoleOutput::cerr ( ) << "Process::finalize. Erreur lors de l'appel à kill pour le processus de PID " << (unsigned long)*itk << " : " << strerror (errno) << co_endl;
458+
} // if (0 != res)
459+
} // for (set<pid_t>::iterator itk = _toKill.begin ( ); _toKill.end ( ) != itk; itk++)
460+
461+
_toKill.clear ( );
462+
} // Process::finalize
463+
464+
465+
void Process::killAtEnd (pid_t tokill)
466+
{
467+
_toKill.insert (tokill);
468+
} // Process::killAtEnd
469+
470+
447471
string Process::getChildLine ( )
448472
{
449473
if ((true == isCompleted ( )) && (0 == _childBuffer.length ( )))

src/TkUtil/public/TkUtil/Process.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <siginfo.h>
1212
#endif // !defined(__GNUC__) && !defined(__ia64__)
1313

14+
#include <set>
1415
#include <vector>
1516

1617
#define PROCESS_ERROR_MESSAGE_SIZE (1025)
@@ -286,7 +287,8 @@ class Process
286287
* @param environnement d'execution (3eme argument du main de l'application, où main est défini comme suit :
287288
* int main (int argc, char* argv[], char* envp [])
288289
* @warning il est essentiel d'appeler cette fonction avant le lancement de tout process fils. En son absence
289-
* il est possible que l'exécution du process fils échoue.
290+
* il est possible que l'exécution du process fils échoue.
291+
* @see finalize
290292
*/
291293
static void initialize (int argc, char* argv [], char* envp []);
292294

@@ -300,6 +302,21 @@ class Process
300302
*/
301303
static void initialize (char* envp []);
302304

305+
/**
306+
* Détruit tous les processus dont la destruction a été confiée à cette classe. Ce peut être par exemple des processus
307+
* fils lancés via fork et non attendus.
308+
* @see killAtEnd
309+
* @since 6.13.0
310+
*/
311+
static void finalize ( );
312+
313+
/**
314+
* Délègue à cette classe le fait de tuer le processus de pid transmis en argument lorsque Process::finalize sera appelé.
315+
* @see finalize
316+
* @since 6.13.0
317+
*/
318+
static void killAtEnd (pid_t tokill);
319+
303320
/**
304321
* @return Le répertoire courrant de l'application, ou, en cas d'erreur, une chaine vide.
305322
*/
@@ -455,6 +472,12 @@ class Process
455472
/** La table comprenant les ids des tâches et les pointeurs sur les instances associées de cette classe.
456473
*/
457474
static IN_STD vector<Process*> _tasks;
475+
476+
/**
477+
* Les processus à tuer à lappel de finalize.
478+
* @see killAtEnd
479+
*/
480+
static IN_STD set<pid_t> _toKill;
458481

459482
/** Le nombre d'arguments de lancement de cette application. */
460483
static int _argc;

versions.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
Version 6.13.0 : 14/03/25
2+
=================
3+
4+
Possibilité de déléguer à la classe Process la destruction de processus en fin d'exécution via Process::killAtEnd () et Process::finalize ().
5+
6+
17
Version 6.12.1 : 12/03/25
28
=================
39

0 commit comments

Comments
 (0)