Bonjour tout le monde,

Je travaille actuellement sur une fonction capable de lancer un programme (ou une fonction perl) en tâche de fond, une fois cette fonction appelée, elle renvoie une liste avec les descripteurs STDIN, STDOUT et STDERR du process parent, eux même liés aux descripteurs STDIN, STDOUT et STDERR du process enfant par l'intermédiaire de fichiers temporaires
Pourquoi des fichiers temporaires ? car les tubes nommés peuvent au maximum lire/ecrire 512 octets, les socket ce n'est pas beaucoup mieux avec - quand même - 4096 octets (4ko)

Voici une ébauche de code, qui parfois fonctionne, parfois génère un zombie... Je planche actuellement sur le pourquoi du zombie, mais peut être l'un (ou plusieurs) d'entre vous a/ont déja cette fonction qui traine dans leur package PERL qui leur sert de boite à outils !

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
 
sub myFork($$)
{
	my ($param_dir, $param_cmd) = @_;
	return unless (ref($param_cmd) =~ /^ARRAY$/i || ref($param_cmd));
 
	local $SIG{CLD} = local $SIG{CHLD} = sub { my $stiff; while (($stiff = waitpid(-1, POSIX::WNOHANG())) > 0) { }; };
	local $! = 0;
 
	my $fh_in, my $fh_out, my $fh_err;
	my $pif = sprintf("%08d",int(rand(100000000)));
	my $file_in = "/tmp/fh_in_${pif}_$$.avms";
	my $file_out = "/tmp/fh_out_${pif}_$$.avms";
	my $file_err = "/tmp/fh_err_${pif}_$$.avms";
 
	my $pid;
	die "myFork => fork" unless defined ($pid = fork);
 
	# Partie PARENT :
 
	if ($pid)
	{			
		my $open_in, my $open_out, my $open_err;
 
		# Création du fichier TEMPORAIRE d'entrée ( ou l'ouvre en écriture) ! :
		$open_in = open ($fh_in, '>', $file_in) or die "myFork => parent => open => in";
 
		if ($open_in)
		{
			my $old_fh = select($fh_in); $| = 1; select($old_fh);
		}
 
		# Puis du fichier TEMPORAIRE de sortie (on tente de l'ouvrir en lecture) :
		my $ind = 0;
 
		while ($ind <= 15)
		{
			$open_out = open ($fh_out, '<', $file_out);
			last if $open_out;
 
			$ind++;
			select(undef,undef,undef,0.1 * $ind);
		}
 
		die "myFork => parent => open => out" unless (defined($open_out));
 
		# Puis du fichier TEMPORAIRE des erreurs (on tente de l'ouvrir en lecture) :
		$ind = 0;
 
		while ($ind <= 15)
		{
			$open_err = open ($fh_err, '<', $file_err);
			last if $open_err;
 
			$ind++;
			select(undef,undef,undef,0.1 * $ind);
		}
 
		die "myFork => parent => open => err" unless (defined($open_err));
 
		return ($fh_in,$fh_out,$fh_err);
	}
	else
	# Partie ENFANT :
	{
		my $LOOP = 1;
 
		local $SIG{TERM} = local $SIG{INT} = sub { $LOOP = 0; };
 
		my $fh_in, my $fh_out, my $fh_err;
		my $open_in, my $open_out, my $open_err;
 
		# Création du fichier TEMPORAIRE des erreurs ( ou l'ouvre en écriture) ! :
		$open_err = open ($fh_err, '>', $file_err) or die "myFork => child => open => err";
 
		if ($open_err)
		{
			#close STDERR;
			open(STDERR, '>&' . CORE::fileno($fh_err)) or die "myFork => child => open => stderr";
			my $old_fh = select($fh_err); $| = 1; select(*STDERR); $| = 1; select($old_fh);
		}
 
		# Création du fichier TEMPORAIRE de sortie ( ou l'ouvre en écriture) ! :
		$open_out = open ($fh_out, '>', $file_out) or die "myFork => child => open => out";
 
		if ($open_out)
		{
			my $old_fh = select($fh_out); $| = 1; select($old_fh);
			#close STDOUT;
			open(STDOUT, '>&' . CORE::fileno($fh_out)) or die "myFork => child => open => stdout";
			$old_fh = select(*STDOUT); $| = 1; select($old_fh);
		}
 
		# Création du fichier TEMPORAIRE d'entrée (on ouvre en lecture) :
		my $ind=0;
 
		while ($ind <= 15)
		{
			$open_in = open ($fh_in, '<', $file_in);
			last if $open_in;
 
			$ind++;
			select(undef,undef,undef,0.1 * $ind);
		}
 
		unless (defined($open_in))
		{
			die "myFork => child => open => in";
		}
		else
		{
			close STDIN;
			open(STDIN, '<&' . CORE::fileno($fh_in));
		}
 
		# Lancement ! :
 
		# On attend la création de $file_in, $file_out et $file_err :
		$ind = 0;
 
		while ($ind <= 15)
		{
			last if (-r $file_in && -w $file_out && -w $file_err);
 
			$ind++;
			select(undef,undef,undef,0.1 * $ind);
		}			
 
		# Démo :
		while ($LOOP)
		{
			my $ligne = <STDIN>;
			chomp($ligne);
			print "RECU: $ligne\n";
 
			select(undef,undef,undef,0.2);
		}
 
		#chdir ($param_dir);
		#exec (@$param_cmd);
		#die "MORT: $!\n";
 
		exit;
	}
}
Normalement, la fonction s'apelle comme ca :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
my ($in,$out,$err) = myFork("/chemin/vers/exe", ["perl","truc.pl"]);