Fixed open descriptor issue with agentupdate on linux/freebsd
Bryan Roe committed
Jan 27, 2021 at 00:43 UTC
fe9baf0e8ff07eaf171c08cc064f3e60009ff058
2 files changed
+195
-7
agents/meshcore.js
+92
-3
@@ -3760,7 +3760,87 @@ function sendAgentMessage(msg, icon) {
3760
sendAgentMessage.messages[sendAgentMessage.nextid++] = { msg: msg, icon: icon };
3761
require('MeshAgent').SendCommand({ action: 'sessions', type: 'msg', value: sendAgentMessage.messages });
3762
}
3763
-
3763
+function getOpenDescriptors()
3764
+{
3765
+ switch (process.platform)
3766
+ {
3767
+ case "freebsd":
3768
+ var child = require('child_process').execFile('/bin/sh', ['sh']);
3769
+ child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3770
+ child.stderr.on('data', function (c) { });
3771
+
3772
+ child.stdin.write("procstat -f " + process.pid + " | tr '\\n' '`' | awk -F'`' '");
3773
+ child.stdin.write('{');
3774
+ child.stdin.write(' DEL="";');
3775
+ child.stdin.write(' printf "[";');
3776
+ child.stdin.write(' for(i=1;i<NF;++i)');
3777
+ child.stdin.write(' {');
3778
+ child.stdin.write(' A=split($i,B," ");');
3779
+ child.stdin.write(' if(B[3] ~ /^[0-9]/)');
3780
+ child.stdin.write(' {');
3781
+ child.stdin.write(' printf "%s%s", DEL, B[3];');
3782
+ child.stdin.write(' DEL=",";');
3783
+ child.stdin.write(' }');
3784
+ child.stdin.write(' }');
3785
+ child.stdin.write(' printf "]";');
3786
+ child.stdin.write("}'");
3787
+
3788
+ child.stdin.write('\nexit\n');
3789
+ child.waitExit();
3790
+
3791
+ try
3792
+ {
3793
+ return (JSON.parse(child.stdout.str.trim()));
3794
+ }
3795
+ catch (e)
3796
+ {
3797
+ return ([]);
3798
+ }
3799
+ break;
3800
+ case "linux":
3801
+ var child = require('child_process').execFile('/bin/sh', ['sh']);
3802
+ child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
3803
+ child.stderr.on('data', function (c) { });
3804
+
3805
+ child.stdin.write("ls /proc/" + process.pid + "/fd | tr '\\n' '`' | awk -F'`' '");
3806
+ child.stdin.write('{');
3807
+ child.stdin.write(' printf "[";');
3808
+ child.stdin.write(' DEL="";');
3809
+ child.stdin.write(' for(i=1;i<NF;++i)');
3810
+ child.stdin.write(' {');
3811
+ child.stdin.write(' printf "%s%s",DEL,$i;');
3812
+ child.stdin.write(' DEL=",";');
3813
+ child.stdin.write(' }');
3814
+ child.stdin.write(' printf "]";');
3815
+ child.stdin.write("}'");
3816
+ child.stdin.write('\nexit\n');
3817
+ child.waitExit();
3818
+
3819
+ try
3820
+ {
3821
+ return (JSON.parse(child.stdout.str.trim()));
3822
+ }
3823
+ catch (e)
3824
+ {
3825
+ return ([]);
3826
+ }
3827
+ break;
3828
+ default:
3829
+ return ([]);
3830
+ }
3831
+}
3832
+function closeDescriptors(libc, descriptors)
3833
+{
3834
+ var fd = null;
3835
+ while (descriptors.length > 0)
3836
+ {
3837
+ fd = descriptors.pop();
3838
+ if (fd > 2)
3839
+ {
3840
+ libc.close(fd);
3841
+ }
3842
+ }
3843
+}
3844
function linux_execv(name, agentfilename, sessionid) {
3845
var libs = require('monitor-info').getLibInfo('libc');
3846
var libc = null;
@@ -3778,6 +3858,7 @@ function linux_execv(name, agentfilename, sessionid) {
3858
if (libc != null) {
3859
try {
3860
libc.CreateMethod('execv');
3861
+ libc.CreateMethod('close');
3862
}
3863
catch (e) {
3864
libc = null;
@@ -3803,7 +3884,7 @@ function linux_execv(name, agentfilename, sessionid) {
3884
3885
var i;
3886
var args;
3806
- var argarr = [];
3887
+ var argarr = [process.execPath];
3888
var path = require('_GenericMarshal').CreateVariable(process.execPath);
3889
3890
if (require('MeshAgent').getStartupOptions != null) {
@@ -3819,6 +3900,9 @@ function linux_execv(name, agentfilename, sessionid) {
3900
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
3901
}
3902
3903
+ var descriptors = getOpenDescriptors();
3904
+ closeDescriptors(libc, descriptors);
3905
+
3906
libc.execv(path, args);
3907
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
3908
sendAgentMessage('Self Update failed because execv() failed', 3);
@@ -3849,6 +3933,7 @@ function bsd_execv(name, agentfilename, sessionid) {
3933
try {
3934
libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim());
3935
libc.CreateMethod('execv');
3936
+ libc.CreateMethod('close');
3937
}
3938
catch (e) {
3939
if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) }
@@ -3858,7 +3943,7 @@ function bsd_execv(name, agentfilename, sessionid) {
3943
3944
var i;
3945
var path = require('_GenericMarshal').CreateVariable(process.execPath);
3861
- var argarr = [];
3946
+ var argarr = [process.execPath];
3947
var args;
3948
var options = require('MeshAgent').getStartupOptions();
3949
for (i in options) {
@@ -3871,6 +3956,10 @@ function bsd_execv(name, agentfilename, sessionid) {
3956
}
3957
3958
if (sessionid != null) { sendConsoleText('Restarting service via execv()', sessionid) }
3959
+
3960
+ var descriptors = getOpenDescriptors();
3961
+ closeDescriptors(libc, descriptors);
3962
+
3963
libc.execv(path, args);
3964
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
3965
sendAgentMessage('Self Update failed because execv() failed', 3);
agents/recoverycore.js
+103
-4
@@ -71,6 +71,77 @@ function MeshServerLogEx(id, args, msg, state) {
71
require('MeshAgent').SendCommand(msg);
72
}
73
74
+function getOpenDescriptors()
75
+{
76
+ switch(process.platform)
77
+ {
78
+ case "freebsd":
79
+ var child = require('child_process').execFile('/bin/sh', ['sh']);
80
+ child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
81
+ child.stderr.on('data', function (c) { });
82
+
83
+ child.stdin.write("procstat -f " + process.pid + " | tr '\\n' '`' | awk -F'`' '");
84
+ child.stdin.write('{');
85
+ child.stdin.write(' DEL="";');
86
+ child.stdin.write(' printf "[";');
87
+ child.stdin.write(' for(i=1;i<NF;++i)');
88
+ child.stdin.write(' {');
89
+ child.stdin.write(' A=split($i,B," ");');
90
+ child.stdin.write(' if(B[3] ~ /^[0-9]/)');
91
+ child.stdin.write(' {');
92
+ child.stdin.write(' printf "%s%s", DEL, B[3];');
93
+ child.stdin.write(' DEL=",";');
94
+ child.stdin.write(' }');
95
+ child.stdin.write(' }');
96
+ child.stdin.write(' printf "]";');
97
+ child.stdin.write("}'");
98
+
99
+ child.stdin.write('\nexit\n');
100
+ child.waitExit();
101
+
102
+ try
103
+ {
104
+ return(JSON.parse(child.stdout.str.trim()));
105
+ }
106
+ catch(e)
107
+ {
108
+ return ([]);
109
+ }
110
+ break;
111
+ case "linux":
112
+ var child = require('child_process').execFile('/bin/sh', ['sh']);
113
+ child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
114
+ child.stderr.on('data', function (c) { });
115
+
116
+ child.stdin.write("ls /proc/" + process.pid + "/fd | tr '\\n' '`' | awk -F'`' '");
117
+ child.stdin.write('{');
118
+ child.stdin.write(' printf "[";');
119
+ child.stdin.write(' DEL="";');
120
+ child.stdin.write(' for(i=1;i<NF;++i)');
121
+ child.stdin.write(' {');
122
+ child.stdin.write(' printf "%s%s",DEL,$i;');
123
+ child.stdin.write(' DEL=",";');
124
+ child.stdin.write(' }');
125
+ child.stdin.write(' printf "]";');
126
+ child.stdin.write("}'");
127
+ child.stdin.write('\nexit\n');
128
+ child.waitExit();
129
+
130
+ try
131
+ {
132
+ return (JSON.parse(child.stdout.str.trim()));
133
+ }
134
+ catch (e)
135
+ {
136
+ return ([]);
137
+ }
138
+ break;
139
+ default:
140
+ return ([]);
141
+ }
142
+}
143
+
144
+
145
function pathjoin() {
146
var x = [];
147
for (var i in arguments) {
@@ -89,6 +160,20 @@ function pathjoin() {
160
// Replace a string with a number if the string is an exact number
161
function toNumberIfNumber(x) { if ((typeof x == 'string') && (+parseInt(x) === x)) { x = parseInt(x); } return x; }
162
163
+
164
+function closeDescriptors(libc, descriptors)
165
+{
166
+ var fd = null;
167
+ while(descriptors.length>0)
168
+ {
169
+ fd = descriptors.pop();
170
+ if(fd > 2)
171
+ {
172
+ libc.close(fd);
173
+ }
174
+ }
175
+}
176
+
177
function linux_execv(name, agentfilename, sessionid) {
178
var libs = require('monitor-info').getLibInfo('libc');
179
var libc = null;
@@ -104,8 +189,10 @@ function linux_execv(name, agentfilename, sessionid) {
189
}
190
}
191
if (libc != null) {
107
- try {
192
+ try
193
+ {
194
libc.CreateMethod('execv');
195
+ libc.CreateMethod('close');
196
}
197
catch (e) {
198
libc = null;
@@ -131,7 +218,7 @@ function linux_execv(name, agentfilename, sessionid) {
218
219
var i;
220
var args;
134
- var argarr = [];
221
+ var argarr = [process.execPath];
222
var path = require('_GenericMarshal').CreateVariable(process.execPath);
223
224
if (require('MeshAgent').getStartupOptions != null) {
@@ -147,6 +234,9 @@ function linux_execv(name, agentfilename, sessionid) {
234
arg.pointerBuffer().copy(args.toBuffer(), i * require('_GenericMarshal').PointerSize);
235
}
236
237
+ var descriptors = getOpenDescriptors();
238
+ closeDescriptors(libc, descriptors);
239
+
240
libc.execv(path, args);
241
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
242
sendAgentMessage('Self Update failed because execv() failed', 3);
@@ -174,9 +264,11 @@ function bsd_execv(name, agentfilename, sessionid) {
264
}
265
266
var libc = null;
177
- try {
267
+ try
268
+ {
269
libc = require('_GenericMarshal').CreateNativeProxy(child.stdout.str.trim());
270
libc.CreateMethod('execv');
271
+ libc.CreateMethod('close');
272
}
273
catch (e) {
274
if (sessionid != null) { sendConsoleText('Self Update failed: ' + e.toString(), sessionid) }
@@ -186,7 +278,7 @@ function bsd_execv(name, agentfilename, sessionid) {
278
279
var i;
280
var path = require('_GenericMarshal').CreateVariable(process.execPath);
189
- var argarr = [];
281
+ var argarr = [process.execPath];
282
var args;
283
var options = require('MeshAgent').getStartupOptions();
284
for (i in options) {
@@ -199,6 +291,10 @@ function bsd_execv(name, agentfilename, sessionid) {
291
}
292
293
if (sessionid != null) { sendConsoleText('Restarting service via execv()', sessionid) }
294
+
295
+ var descriptors = getOpenDescriptors();
296
+ closeDescriptors(libc, descriptors);
297
+
298
libc.execv(path, args);
299
if (sessionid != null) { sendConsoleText('Self Update failed because execv() failed', sessionid) }
300
sendAgentMessage('Self Update failed because execv() failed', 3);
@@ -905,6 +1001,9 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
1001
case 'help':
1002
response = "Available commands are: agentupdate, dbkeys, dbget, dbset, dbcompact, eval, netinfo, osinfo, setdebug, versions.";
1003
break;
1004
+ case '_descriptors':
1005
+ response = 'Open Descriptors: ' + JSON.stringify(getOpenDescriptors());
1006
+ break;
1007
case 'versions':
1008
response = JSON.stringify(process.versions, null, ' ');
1009
break;