mongrel_service 0.3.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/native/_debug.bi ADDED
@@ -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__