Skip to content

Commit 7927dcf

Browse files
authored
Merge pull request #9386 from tvpartytonight/PA-6394
(PA-6394) Stop using FFI threads and use ruby threads for the windows puppet daemon
2 parents ad07a6f + d6386ac commit 7927dcf

File tree

2 files changed

+66
-32
lines changed

2 files changed

+66
-32
lines changed
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
test_name 'Test agent state via service control manager' do
2+
3+
tag 'audit:integration'
4+
5+
confine :to, platform: 'windows'
6+
7+
teardown do
8+
agents.each do |agent|
9+
state = query_agent_state(agent)
10+
if state != "STOPPED"
11+
stop_puppet_windows_daemon(agent)
12+
ensure_agent_state(agent, "STOPPED")
13+
end
14+
end
15+
end
16+
17+
def query_agent_state(host)
18+
on(host, 'sc query puppet').stdout.match(/STATE.+\s{1}(\w+)/)[1]
19+
end
20+
21+
def start_puppet_windows_daemon(host)
22+
on(host, 'sc start puppet')
23+
end
24+
25+
def stop_puppet_windows_daemon(host)
26+
on(host, 'sc stop puppet')
27+
end
28+
29+
def ensure_agent_state(host, state)
30+
retry_attempts = 0
31+
while retry_attempts < 5
32+
return if state == query_agent_state(host)
33+
retry_attempts += 1
34+
sleep 1
35+
end
36+
fail_test "State not #{state} after 5 tries"
37+
end
38+
39+
step 'store initial state' do
40+
41+
agents.each do |agent|
42+
initial_state = query_agent_state(agent)
43+
assert_match("STOPPED", initial_state, "agent daemon should initially be stopped")
44+
45+
start_puppet_windows_daemon(agent)
46+
ensure_agent_state(agent, "RUNNING")
47+
stop_puppet_windows_daemon(agent)
48+
ensure_agent_state(agent, "STOPPED")
49+
end
50+
end
51+
end

Diff for: lib/puppet/util/windows/daemon.rb

+15-32
Original file line numberDiff line numberDiff line change
@@ -187,25 +187,6 @@ class Daemon
187187
SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
188188
end
189189

190-
ThreadProc = FFI::Function.new(:ulong, [:pointer]) do |lpParameter|
191-
ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRYW, 2)
192-
193-
s = SERVICE_TABLE_ENTRYW.new(ste[0])
194-
s[:lpServiceName] = FFI::MemoryPointer.from_string('')
195-
s[:lpServiceProc] = lpParameter
196-
197-
s = SERVICE_TABLE_ENTRYW.new(ste[1])
198-
s[:lpServiceName] = nil
199-
s[:lpServiceProc] = nil
200-
201-
# No service to step, no service handle, no ruby exceptions, just terminate the thread..
202-
unless StartServiceCtrlDispatcherW(ste)
203-
return 1
204-
end
205-
206-
return 0
207-
end
208-
209190
# This is a shortcut for Daemon.new + Daemon#mainloop.
210191
#
211192
def self.mainloop
@@ -255,26 +236,28 @@ def mainloop
255236
raise SystemCallError.new('CreateEvent', FFI.errno)
256237
end
257238

258-
hThread = CreateThread(nil, 0, ThreadProc, Service_Main, 0, nil)
239+
hThread = Thread.new do
240+
ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRYW, 2)
259241

260-
if hThread == 0
261-
raise SystemCallError.new('CreateThread', FFI.errno)
262-
end
242+
s = SERVICE_TABLE_ENTRYW.new(ste[0])
243+
s[:lpServiceName] = FFI::MemoryPointer.from_string("")
244+
s[:lpServiceProc] = Service_Main
263245

264-
events = FFI::MemoryPointer.new(:pointer, 2)
265-
events.put_pointer(0, FFI::Pointer.new(hThread))
266-
events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent))
246+
s = SERVICE_TABLE_ENTRYW.new(ste[1])
247+
s[:lpServiceName] = nil
248+
s[:lpServiceProc] = nil
267249

268-
while (index = WaitForMultipleObjects(2, events, 0, 1000)) == WAIT_TIMEOUT
250+
# No service to step, no service handle, no ruby exceptions, just terminate the thread..
251+
StartServiceCtrlDispatcherW(ste)
269252
end
270253

271-
if index == WAIT_FAILED
272-
raise SystemCallError.new('WaitForMultipleObjects', FFI.errno)
254+
while (index = WaitForSingleObject(@@hStartEvent, 1000)) == WAIT_TIMEOUT
255+
# The thread exited, so the show is off.
256+
raise "Service_Main thread exited abnormally" unless hThread.alive?
273257
end
274258

275-
# The thread exited, so the show is off.
276-
if index == WAIT_OBJECT_0
277-
raise "Service_Main thread exited abnormally"
259+
if index == WAIT_FAILED
260+
raise SystemCallError.new("WaitForSingleObject", FFI.errno)
278261
end
279262

280263
thr = Thread.new do

0 commit comments

Comments
 (0)