|
Author: Christian A.
Pradelli Date: 04/20/2007 kbmMW
version: 2.61 Wine version 0.9.30
Introduction
I did this tutorial because after
some time dealing with a Kylix compiled kbmMWserver I arrived to the conclusion
that today it is a waste of time to work with Kylix if you can avoid
it.
It works fine, but any time you have
a problem is very hard to find and fix it (right now, debug is only possible
using GDB debbuger). Other problem is that after all that effort you can only
compile to 32 bit linux, not 64bits, FreeBsd, MacOs, etc.
One day on a production server I
found a bug in my Kylix kbmMWserver application that takes me an entire day to
solve it, so during that time I leave the windows version running with Wine to
let my customer work. At that moment I discover that it performs at the same
speed that the Kylix version and sometimes faster. So I did I extensive
benchmarks that report that a Delphi 7 compiled server under wine performs at
the same speed that a Kylix 3 compiled one most the time and some times perform
up to 20% faster than the Kylix compiled server.
How can this be possible?, basically
wine is not an emulator, it provides the libraries to let a windows application
run under Linux and only make some kind of emulation when the application needs
to interface with the OS, so if the application does not perform any operation
with X server it practically doesn't suffer any performance penalty. How can it
be faster?, because in Delphi 7 you can use some high optimized libraries like
FastZLib that performs better that the ones that are available to
Kylix.
Running a kbmMWserver using wine is
very safe a stable, I tested it under heavy load (40 concurrent and demanding
connections) and I never have a crash.
I'm not considering FreePascal at
this moment, may be in the near future we can use it for compile kbmMWserver
application to 64bits platforms where I think we will get better
performance.
Requirements
To make a kbmMWserver application to
work as a Linux daemon using wine, the application should not make any call to
the X server. To do that, you must ensure that the application should not use
the Forms unit at all.
A simple trick to confirm that Forms
unit is not used in any place, is to temporally rename Forms.dcu in Delphi7\Lib
directory to Forms.dcu.xxx and rebuild application, it Forms is not used the
application will compile successfully and it size will be about 300k less than
with Form unit included.
Also doing this you can run on a
Linux server that have no X server installed.
Example
Following you will find a project
example to make you server without Forms unit (because without it you don't have
the Application variable), and at the end I put and script example to use it
under Ubuntu (you can easily change to other Linux).
**************************************************************************************************** winedaemon.dpr ****************************************************************************************************
program winedaemon;
uses Windows,
System, SysUtils, Srv1 in
'Srv1.pas' {Main: TDataModule};
{$R *.res}
var fAplNme:
string; LogFile: string =
''; ShutNme: string;
ShutHdl: THandle; StopNme: string;
StopHdl: Thandle;
// do a log procedure
DoLog(s: string); var TFile:
TextFile; begin if
LogFile = '' then
WriteLn(s) else try AssignFile(TFile,
LogFile);
try
Append(TFile);
except
Rewrite(TFile);
end;
try WriteLn(TFile,
dato);
finally
CloseFile(TFile);
end; except end; end;
// this only work if you use wineconsole, but
wineconsole doesn't work a a daemon function
ConProc(CtrlType : DWord) : Bool; stdcall; far; begin // a KILL SIGINT (2) is the same as
CTRL_C_EVENT if CtrlType in
[CTRL_C_EVENT,CTRL_BREAK_EVENT,CTRL_CLOSE_EVENT,CTRL_LOGOFF_EVENT
,CTRL_SHUTDOWN_EVENT] then if not
SetEvent(ShutHdl) then DoLog('Can't stop
server'); Result := True; end;
begin fAplNme
:= ParamStr(0); if FindCmdLineSwitch('?',True) then
begin WriteLn('options: -outlog
-shutdown'); Exit; end;
ShutNme :=
StringReplace(fAplNme,'\','/',[rfReplaceAll])+'-shutdown'; StopNme
:=
StringReplace(fAplNme,'\','/',[rfReplaceAll])+'-stoped'; ShutHdl
:= OpenEvent(EVENT_ALL_ACCESS,False,PChar(ShutNme));
// the
log will be done to a file if
FindCmdLineSwitch('outlog',True) then LogFile :=
ChangeFileExt(fAplNme,'.log');
// stop the server if it's
executing if FindCmdLineSwitch('shutdown',True)
then begin if ShutHdl = 0
then DoLog('shutdown –
The server is not running')
else begin StopHdl :=
CreateEvent(nil,False,False,PChar(StopNme)); if
SetEvent(ShutHdl) then
WaitForSingleObject(StopHdl, 10000) // espero como maximo 10 segundos a que
termine
else
DoLog('shutdown – Can't stop server'); end; Exit; end else if
ShutHdl <> 0 then begin DoLog('The server is already
running'); Exit; end;
//
start server DoLog('Starting
server'); Main := Tmain.Create(nil); // here you
create the main kbmMWServer datamodule and configure it
try // I create an event to trap
shutdown signal ShutHdl :=
CreateEvent(nil,False,False,PChar(ShutNme)); if ShutHdl = 0
then DoLog('Error
creating stop event');
// start kbmMW
server Main.Srv.Active :=
True; DoLog('Server
started');
// trap ctr-c if you are
running in a console with wineconsole SetConsoleCtrlHandler(@ConProc,
True);
// here we wait until
shutdown WaitForSingleObject(ShutHdl,
INFINITE);
// stop the
server Main.Srv.Active :=
False;
// signal that I already
shutdown StopHdl :=
OpenEvent(EVENT_ALL_ACCESS,False,PChar(StopNme)); if StopHdl <> 0
then
SetEvent(StopHdl); finally
Main.Free; DoLog('Server
stoped'); end;
end.
**************************************************************************************************** init.d script
for ubuntu **************************************************************************************************** #!/bin/sh # # Start/Stop
Wine Server # # # This file belongs in /etc/init.d where it will
be run # on system startup and shutdown to start the
background # Wine Sever daemon
# Source
function library. #.
/etc/init.d/functions
APP_NAME=winedaemon APP_BIN=/home/user/mydaemon/$APP_NAME APP_USER=user
case "$1"
in start) echo -n "Starting $APP_NAME: "
sudo -u $APP_USER /usr/bin/wine $APP_BIN -outlog
> /dev/null 2>&1 & RETVAL=$? echo ;;
stop) echo -n
"Stopping $APP_NAME: " sudo -u
$APP_USER /usr/bin/wine $APP_BIN -shutdown
RETVAL=$? echo ;;
status) # to
do RETVAL=$?
;;
restart|reload)
$0 stop $0
start RETVAL=$? ;;
*) echo "Usage:
winedaemond {start|stop|status|restart|reload}"
exit 1 esac
exit
$?
(Top)
|