mongrel_service 0.3.4-i386-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,59 @@
1
+ '##################################################################
2
+ '#
3
+ '# mongrel_service: Win32 native implementation for mongrel
4
+ '# (using ServiceFB and FreeBASIC)
5
+ '#
6
+ '# Copyright (c) 2006 Multimedia systems
7
+ '# (c) and code by Luis Lavena
8
+ '#
9
+ '# mongrel_service (native) and mongrel_service gem_pluing are licensed
10
+ '# in the same terms as mongrel, please review the mongrel license at
11
+ '# http://mongrel.rubyforge.org/license.html
12
+ '#
13
+ '##################################################################
14
+
15
+ '##################################################################
16
+ '# Requirements:
17
+ '# - FreeBASIC 0.17, Win32 CVS Build (as for November 09, 2006).
18
+ '#
19
+ '##################################################################
20
+
21
+ #ifndef __Debug_bi__
22
+ #define __Debug_bi__
23
+
24
+ #ifdef DEBUG_LOG
25
+ #include once "vbcompat.bi"
26
+ #ifndef DEBUG_LOG_FILE
27
+ #define DEBUG_LOG_FILE EXEPATH + "\debug.log"
28
+ #endif
29
+
30
+ '# this procedure is only used for debugging purposed, will be removed from
31
+ '# final compilation
32
+ private sub debug_to_file(byref message as string, byref file as string, byval linenumber as uinteger, byref func as string)
33
+ dim handle as integer
34
+ static first_time as integer
35
+
36
+ handle = freefile
37
+ open DEBUG_LOG_FILE for append as #handle
38
+
39
+ if (first_time = 0) then
40
+ print #handle, "# Logfile created on "; format(now(), "dd/mm/yyyy HH:mm:ss")
41
+ print #handle, ""
42
+ first_time = 1
43
+ end if
44
+
45
+ '# src/module.bas:123, namespace.function:
46
+ '# message
47
+ '#
48
+ print #handle, file; ":"; str(linenumber); ", "; lcase(func); ":"
49
+ print #handle, space(2); message
50
+ print #handle, ""
51
+
52
+ close #handle
53
+ end sub
54
+ #define debug(message) debug_to_file(message, __FILE__, __LINE__, __FUNCTION__)
55
+ #else
56
+ #define debug(message)
57
+ #endif '# DEBUG_LOG
58
+
59
+ #endif '# __Debug_bi__
@@ -0,0 +1,389 @@
1
+ '#--
2
+ '# Copyright (c) 2007 Luis Lavena, Multimedia systems
3
+ '#
4
+ '# This source code is released under the MIT License.
5
+ '# See MIT-LICENSE file for details
6
+ '#++
7
+
8
+ #include once "console_process.bi"
9
+
10
+ constructor ConsoleProcess(byref new_filename as string = "", byref new_arguments as string = "")
11
+ '# assign filename and arguments
12
+
13
+ '# if filename contains spaces, automatically quote it!
14
+ if (instr(new_filename, " ") > 0) then
15
+ _filename = !"\"" + new_filename + !"\""
16
+ else
17
+ _filename = new_filename
18
+ endif
19
+
20
+ _arguments = new_arguments
21
+ end constructor
22
+
23
+ destructor ConsoleProcess()
24
+ '# in case process still running
25
+ if (running = true) then
26
+ terminate(true)
27
+
28
+ '# close opened handles
29
+ '# ...
30
+ CloseHandle(_process_info.hProcess)
31
+ CloseHandle(_process_info.hThread)
32
+ end if
33
+ end destructor
34
+
35
+ property ConsoleProcess.filename() as string
36
+ return _filename
37
+ end property
38
+
39
+ property ConsoleProcess.filename(byref rhs as string)
40
+ if not (running = true) then
41
+ _filename = rhs
42
+ end if
43
+ end property
44
+
45
+ property ConsoleProcess.arguments() as string
46
+ return _arguments
47
+ end property
48
+
49
+ property ConsoleProcess.arguments(byref rhs as string)
50
+ if not (running = true) then
51
+ _arguments = rhs
52
+ end if
53
+ end property
54
+
55
+ property ConsoleProcess.redirected_stdout() as string
56
+ return _stdout_filename
57
+ end property
58
+
59
+ property ConsoleProcess.redirected_stderr() as string
60
+ return _stderr_filename
61
+ end property
62
+
63
+ '# running is a helper which evaluates _pid and exit_code
64
+ property ConsoleProcess.running() as boolean
65
+ dim result as boolean
66
+
67
+ '# presume not running
68
+ result = false
69
+
70
+ if not (_pid = 0) then
71
+ '# that means the process is/was running.
72
+ '# now evaluate if exit_code = STILL_ACTIVE
73
+ result = (exit_code = STILL_ACTIVE)
74
+ end if
75
+
76
+ return result
77
+ end property
78
+
79
+ property ConsoleProcess.pid() as uinteger
80
+ return _pid
81
+ end property
82
+
83
+ property ConsoleProcess.exit_code() as uinteger
84
+ dim result as uinteger
85
+
86
+ result = 0
87
+
88
+ '# is _pid valid?
89
+ if not (_pid = 0) then
90
+ if not (_process_info.hProcess = NULL) then
91
+ '# the process reference is valid, get the exit_code
92
+ if not (GetExitCodeProcess(_process_info.hProcess, @result) = 0) then
93
+ '# OK
94
+ '# no error in the query, get result
95
+ end if '# not (GetExitCodeProcess() = 0)
96
+ end if '# not (proc = NULL)
97
+ end if '# not (_pid = 0)
98
+
99
+ return result
100
+ end property
101
+
102
+ function ConsoleProcess.redirect(byval target as ProcessStdEnum, byref new_std_filename as string) as boolean
103
+ dim result as boolean
104
+
105
+ if not (running = true) then
106
+ select case target
107
+ case ProcessStdOut:
108
+ _stdout_filename = new_std_filename
109
+ result = true
110
+
111
+ case ProcessStdErr:
112
+ _stderr_filename = new_std_filename
113
+ result = true
114
+
115
+ case ProcessStdBoth:
116
+ _stdout_filename = new_std_filename
117
+ _stderr_filename = new_std_filename
118
+ result = true
119
+
120
+ end select
121
+ end if
122
+
123
+ return result
124
+ end function
125
+
126
+ function ConsoleProcess.start() as boolean
127
+ dim result as boolean
128
+ dim success as boolean
129
+
130
+ '# API
131
+ '# New Process resources
132
+ dim context as STARTUPINFO
133
+ dim proc_sa as SECURITY_ATTRIBUTES = type(sizeof(SECURITY_ATTRIBUTES), NULL, TRUE)
134
+
135
+ '# StdIn, StdOut, StdErr Read and Write Pipes.
136
+ dim as HANDLE StdInRd, StdOutRd, StdErrRd
137
+ dim as HANDLE StdInWr, StdOutWr, StdErrWr
138
+ dim merged as boolean
139
+
140
+ '# cmdline
141
+ dim cmdline as string
142
+
143
+ '# assume start will fail
144
+ result = false
145
+
146
+ if (running = false) then
147
+ '# we should create the std* for the new proc!
148
+ '# (like good parents, prepare everything!)
149
+
150
+ '# to ensure everything will work, we must allocate a console
151
+ '# using AllocConsole, even if it fails.
152
+ '# This solve the problems when running as service.
153
+ '# we discard result of AllocConsole since we ALWAYS will allocate it.
154
+ AllocConsole()
155
+
156
+ '# assume all the following steps succeed
157
+ success = true
158
+
159
+ '# StdIn is the only std that will be created using pipes always
160
+ '# StdIn
161
+ if (CreatePipe(@StdInRd, @StdInWr, @proc_sa, 0) = 0) then
162
+ success = false
163
+ end if
164
+
165
+ '# Ensure the handles to the pipe are not inherited.
166
+ if (SetHandleInformation(StdInWr, HANDLE_FLAG_INHERIT, 0) = 0) then
167
+ success = false
168
+ end if
169
+
170
+ '# StdOut and StdErr should be redirected?
171
+ if (not _stdout_filename = "") or _
172
+ (not _stderr_filename = "") then
173
+
174
+ '# out and err are the same? (merged)
175
+ if (_stdout_filename = _stderr_filename) then
176
+ merged = true
177
+ end if
178
+ end if
179
+
180
+ '# StdOut if stdout_filename
181
+ if not (_stdout_filename = "") then
182
+ StdOutWr = CreateFile(strptr(_stdout_filename), _
183
+ GENERIC_WRITE, _
184
+ FILE_SHARE_READ or FILE_SHARE_WRITE, _
185
+ @proc_sa, _
186
+ OPEN_ALWAYS, _
187
+ FILE_ATTRIBUTE_NORMAL, _
188
+ NULL)
189
+
190
+ if (StdOutWr = INVALID_HANDLE_VALUE) then
191
+ '# failed to open file
192
+ success = false
193
+ else
194
+ SetFilePointer(StdOutWr, 0, NULL, FILE_END)
195
+ end if
196
+ else
197
+ '# use pipes instead
198
+ '# StdOut
199
+ if (CreatePipe(@StdOutRd, @StdOutWr, @proc_sa, 0) = 0) then
200
+ success = false
201
+ end if
202
+
203
+ if (SetHandleInformation(StdOutRd, HANDLE_FLAG_INHERIT, 0) = 0) then
204
+ success = false
205
+ end if
206
+ end if 'not (_stdout_filename = "")
207
+
208
+ '# only create stderr if no merged.
209
+ if (merged = true) then
210
+ StdErrWr = StdOutWr
211
+ else
212
+ '# do the same for StdErr...
213
+ if not (_stderr_filename = "") then
214
+ StdErrWr = CreateFile(strptr(_stderr_filename), _
215
+ GENERIC_WRITE, _
216
+ FILE_SHARE_READ or FILE_SHARE_WRITE, _
217
+ @proc_sa, _
218
+ OPEN_ALWAYS, _
219
+ FILE_ATTRIBUTE_NORMAL, _
220
+ NULL)
221
+
222
+ if (StdErrWr = INVALID_HANDLE_VALUE) then
223
+ '# failed to open file
224
+ success = false
225
+ else
226
+ SetFilePointer(StdErrWr, 0, NULL, FILE_END)
227
+ end if
228
+ else
229
+ '# use pipes instead
230
+ '# StdOut
231
+ if (CreatePipe(@StdErrRd, @StdErrWr, @proc_sa, 0) = 0) then
232
+ success = false
233
+ end if
234
+
235
+ if (SetHandleInformation(StdErrRd, HANDLE_FLAG_INHERIT, 0) = 0) then
236
+ success = false
237
+ end if
238
+
239
+ end if 'not (_stderr_filename = "")
240
+ end if '(merged = true)
241
+
242
+ '# now we must proceed to create the process
243
+ '# without the pipes, we shouldn't continue!
244
+ if (success = true) then
245
+ '# Set the Std* handles ;-)
246
+ with context
247
+ .cb = sizeof( context )
248
+ .hStdError = StdErrWr
249
+ .hStdOutput = StdOutWr
250
+ .hStdInput = StdInRd
251
+ .dwFlags = STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW
252
+ '# FIXME: .wShowWindow = iif((_show_console = true), SW_SHOW, SW_HIDE)
253
+ .wShowWindow = SW_HIDE
254
+ end with
255
+
256
+ '# build the command line
257
+ cmdline = _filename + " " + _arguments
258
+
259
+ '# now creates the process
260
+ if (CreateProcess(NULL, _
261
+ strptr(cmdline), _
262
+ NULL, _
263
+ NULL, _
264
+ 1, _ '# win32 TRUE (1)
265
+ 0, _
266
+ NULL, _
267
+ NULL, _
268
+ @context, _
269
+ @_process_info) = 0) then
270
+ result = false
271
+ else
272
+ '# set the _pid
273
+ _pid = _process_info.dwProcessId
274
+
275
+ '# OK? yeah, I think so.
276
+ result = true
277
+
278
+ '# close the Std* handles
279
+ CloseHandle(StdInRd)
280
+ CloseHandle(StdInWr)
281
+ CloseHandle(StdOutRd)
282
+ CloseHandle(StdOutWr)
283
+ CloseHandle(StdErrRd)
284
+ CloseHandle(StdErrWr)
285
+
286
+ '# close children main Thread handle
287
+ 'CloseHandle(proc.hThread)
288
+ 'CloseHandle(proc.hProcess)
289
+
290
+ end if '# (CreateProcess() = 0)
291
+ else
292
+ result = false
293
+ end if '# (success = TRUE)
294
+ end if
295
+
296
+ return result
297
+ end function
298
+
299
+ function ConsoleProcess.terminate(byval force as boolean = false) as boolean
300
+ dim result as boolean
301
+ dim success as boolean
302
+
303
+ dim proc as HANDLE
304
+ dim code as uinteger
305
+ dim wait_code as uinteger
306
+
307
+ '# is pid valid?
308
+ if (running = true) then
309
+ '# hook our custom console handler
310
+ if not (SetConsoleCtrlHandler(@_console_handler, 1) = 0) then
311
+ success = true
312
+ end if
313
+
314
+ if (success = true) then
315
+ '# get a handle to Process
316
+ proc = _process_info.hProcess
317
+ if not (proc = NULL) then
318
+ '# process is valid, perform actions
319
+ success = false
320
+
321
+ if not (force = true) then
322
+ '# send CTRL_C_EVENT and wait for result
323
+ if not (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) = 0) then
324
+ '# it worked, wait 5 seconds terminates.
325
+ wait_code = WaitForSingleObject(proc, 5000)
326
+ if not (wait_code = WAIT_TIMEOUT) then
327
+ success = true
328
+ end if
329
+ else
330
+ success = false
331
+ end if
332
+
333
+ '# Ctrl-C didn't work, try Ctrl-Break
334
+ if (success = false) then
335
+ '# send CTRL_BREAK_EVENT and wait for result
336
+ if not (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0) = 0) then
337
+ '# it worked, wait 5 seconds terminates.
338
+ wait_code = WaitForSingleObject(proc, 5000)
339
+ if not (wait_code = WAIT_TIMEOUT) then
340
+ success = true
341
+ end if
342
+ else
343
+ success = false
344
+ end if
345
+ end if
346
+
347
+ '# only do termination if force was set.
348
+ elseif (force = true) and (success = false) then
349
+ '# still no luck? we should do a hard kill then
350
+ if (TerminateProcess(proc, 0) = 0) then
351
+ success = false
352
+ else
353
+ success = true
354
+ end if
355
+ end if
356
+
357
+ '# now get process exit code
358
+ if (success = true) then
359
+ result = true
360
+ else
361
+ result = false
362
+ end if
363
+ else
364
+ '# invalid process handler
365
+ result = false
366
+ end if
367
+
368
+ end if '# (success = true)
369
+
370
+ '# remove hooks
371
+ if not (SetConsoleCtrlHandler(@_console_handler, 0) = 0) then
372
+ success = true
373
+ end if
374
+ end if '# not (pid = 0)
375
+
376
+ return result
377
+ end function
378
+
379
+ function ConsoleProcess._console_handler(byval dwCtrlType as DWORD) as BOOL
380
+ dim result as BOOL
381
+
382
+ if (dwCtrlType = CTRL_C_EVENT) then
383
+ result = 1
384
+ elseif (dwCtrlType = CTRL_BREAK_EVENT) then
385
+ result = 1
386
+ end if
387
+
388
+ return result
389
+ end function
@@ -0,0 +1,75 @@
1
+ '#--
2
+ '# Copyright (c) 2006-2007 Luis Lavena, Multimedia systems
3
+ '#
4
+ '# This source code is released under the MIT License.
5
+ '# See MIT-LICENSE file for details
6
+ '#++
7
+
8
+ #ifndef __CONSOLE_PROCESS_BI__
9
+ #define __CONSOLE_PROCESS_BI__
10
+
11
+ #include once "windows.bi"
12
+ #include once "boolean.bi"
13
+
14
+ enum ProcessStdEnum
15
+ ProcessStdOut = 1
16
+ ProcessStdErr = 2
17
+ ProcessStdBoth = 3
18
+ end enum
19
+
20
+ type ConsoleProcess
21
+ '# this class provide basic functionality
22
+ '# to control child processes
23
+
24
+ '# new ConsoleProcess(Filename, Parameters)
25
+ declare constructor(byref as string = "", byref as string = "")
26
+
27
+ '# delete
28
+ declare destructor()
29
+
30
+ '# properties (only getters)
31
+ declare property filename as string
32
+ declare property filename(byref as string)
33
+
34
+ declare property arguments as string
35
+ declare property arguments(byref as string)
36
+
37
+ '# stdout and stderr allow you redirect
38
+ '# console output and errors to files
39
+ declare property redirected_stdout as string
40
+ declare property redirected_stderr as string
41
+
42
+ '# evaluate if the process is running
43
+ declare property running as boolean
44
+
45
+ '# pid will return the current Process ID, or 0 if no process is running
46
+ declare property pid as uinteger
47
+
48
+ '# exit_code is the value set by the process prior exiting.
49
+ declare property exit_code as uinteger
50
+
51
+ '# methods
52
+ declare function redirect(byval as ProcessStdEnum, byref as string) as boolean
53
+ declare function start() as boolean
54
+ declare function terminate(byval as boolean = false) as boolean
55
+
56
+ private:
57
+ _filename as string
58
+ _arguments as string
59
+ _pid as uinteger
60
+ _process_info as PROCESS_INFORMATION
61
+ _show_console as boolean = false
62
+
63
+ _redirect_stdout as boolean
64
+ _stdout_filename as string
65
+
66
+ _redirect_stderr as boolean
67
+ _stderr_filename as string
68
+
69
+ '# this fake console handler
70
+ '# is used to trap ctrl-c
71
+ declare static function _console_handler(byval as DWORD) as BOOL
72
+
73
+ end type 'ConsoleProcess
74
+
75
+ #endif '__CONSOLE_PROCESS_BI__