28 messages in net.java.dev.jna.usersRe: [jna-users] Win32 Service Callbacks
FromSent OnAttachments
Thomas BörkelAug 21, 2007 6:26 am 
Thomas BörkelAug 22, 2007 12:35 am 
Wayne MeissnerAug 22, 2007 4:38 pm 
Thomas BörkelAug 22, 2007 10:36 pm 
Timothy WallAug 31, 2007 7:23 am 
Thomas BörkelAug 31, 2007 7:47 am 
Timothy WallAug 31, 2007 7:55 am 
Thomas BörkelSep 3, 2007 6:29 am 
Thomas BörkelSep 3, 2007 1:11 pm 
Timothy WallSep 6, 2007 11:21 am 
Thomas BörkelSep 7, 2007 7:08 am 
Timothy WallSep 7, 2007 7:43 am 
Thomas BörkelSep 10, 2007 12:18 am 
Thomas BörkelSep 10, 2007 4:36 am 
Timothy WallSep 10, 2007 5:43 am 
Thomas BörkelSep 10, 2007 6:49 am 
Timothy WallSep 11, 2007 4:47 am 
Thomas BörkelSep 11, 2007 6:15 am 
Timothy WallSep 11, 2007 6:47 am 
Thomas BörkelSep 11, 2007 6:52 am 
Timothy WallSep 11, 2007 8:52 am 
Thomas BörkelSep 11, 2007 10:26 pm 
Timothy WallSep 12, 2007 5:45 am 
Thomas BörkelSep 12, 2007 5:56 am 
Timothy WallSep 12, 2007 6:19 am 
Thomas BörkelSep 12, 2007 7:09 am 
Timothy WallSep 12, 2007 8:17 am 
Thomas BörkelSep 13, 2007 12:58 am 
Actions with this message:
Paste this link in email or IM:
Paste this link in email or IM:
Atom feed for this thread
Paste this URL into your reader:
Subject:Re: [jna-users] Win32 Service CallbacksActions...
From:Thomas Börkel (tho@boerkel.de)
Date:Aug 22, 2007 12:35:05 am
List:net.java.dev.jna.users

HI!

After some more testing, I guess this is some kind of multithreading problem.

If the Service is written in C and the ServiceMain function, that is registered with StartServiceCtrlDispatcher() returns before request to stop the Service, the Service fails to start.

If the Service is written in Java, it does not matter, if the ServiceMain function returns immediatly or not. It still starts OK. This is one difference compared to a C service.

Then, when I am trying to stop the Service: If the ServiceMain function is waiting for an event and the Windows ServiceManager is still able to call the ServiceControl function (registered with RegisterServiceCtrlHandler()), that has to be a on a different thread.

So, the problem may be, that the callback handler was registered on the main thread, but is being called from a different thread.

Any thoughts/hints?

Thanks!

Thomas

HI!

I am trying to write a Win32 service in Java (pretty funny ;-) ).

I have pretty much everything working except the callback from the service control handler.

Another callback (to the service main function) works though.

Since a Win32 service exe is being started without arguments, I have a very small C program that uses CreateProcess() to start "java.exe myClass". This works OK. And then the Java program communicates with the Windows Service Manager using JNA.

I can start the Service with the Service GUI and it signals "running" to the Service Manager.

But when I stop the service, it *should* first receive a callback to the ServiceControl function with parameter "1" (STOP) and then the StartServiceCtrlDispatcher() call returns and the service should report "stopped" to the Service Manager and the program ends.

That's how it works with a C service. But in my case, I do not get the callback to ServiceControl. The StartServiceCtrlDispatcher() call just returns and the Service Manager GUI complains, that the Service would not accept control messages. So, somehow the ServiceControl callback does not work.

However the RegisterServiceCtrlHandler() call worked, because it return non-null.

Some code snippets:

WINSVC.java: interface SERVICE_MAIN_FUNCTION extends StdCallCallback { /* VOID WINAPI ServiceMain( DWORD dwArgc, LPTSTR* lpszArgv );*/ public void callback(int dwArgc, Pointer lpszArgv); }

interface HANDLER extends StdCallCallback { /* VOID WINAPI Handler( DWORD fdwControl );*/ public void callback(int fdwControl); }

/* typedef struct _SERVICE_STATUS { DWORD dwServiceType; DWORD dwCurrentState; DWORD dwControlsAccepted; DWORD dwWin32ExitCode; DWORD dwServiceSpecificExitCode; DWORD dwCheckPoint; DWORD dwWaitHint; } SERVICE_STATUS, *LPSERVICE_STATUS;*/ public static class SERVICE_STATUS extends Structure { public int dwServiceType; public int dwCurrentState; public int dwControlsAccepted; public int dwWin32ExitCode; public int dwServiceSpecificExitCode; public int dwCheckPoint; public int dwWaitHint; }

/* typedef struct _SERVICE_TABLE_ENTRY { LPTSTR lpServiceName; LPSERVICE_MAIN_FUNCTION lpServiceProc; } SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;*/ public static class SERVICE_TABLE_ENTRY extends Structure { public String lpServiceName; public SERVICE_MAIN_FUNCTION lpServiceProc; }

Advapi32.java: /* BOOL WINAPI StartServiceCtrlDispatcher( const SERVICE_TABLE_ENTRY* lpServiceTable );*/ public boolean StartServiceCtrlDispatcher(Structure[] lpServiceTable);

/* SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandler( LPCTSTR lpServiceName, LPHANDLER_FUNCTION lpHandlerProc );*/ public Pointer RegisterServiceCtrlHandler(String lpServiceName, WINSVC.HANDLER lpHandlerProc);

/* BOOL WINAPI SetServiceStatus( SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus );*/ public boolean SetServiceStatus(Pointer hServiceStatus, WINSVC.SERVICE_STATUS lpServiceStatus);

Service.java, main(): WINSVC.SERVICE_TABLE_ENTRY[] entries = new WINSVC.SERVICE_TABLE_ENTRY[2]; WINSVC.SERVICE_TABLE_ENTRY entry;

entry = new WINSVC.SERVICE_TABLE_ENTRY(); entry.lpServiceName = "MailService"; entry.lpServiceProc = new ServiceMain();

advapi32.StartServiceCtrlDispatcher(entry.toArray(2)); // this call blocks until the end

reportStatus(WINSVC.SERVICE_STOPPED, WINERROR.NO_ERROR, 0);

Service.java, reportStatus(): private static void reportStatus(int status, int win32ExitCode, int waitHint) { Advapi32 advapi32; WINSVC.SERVICE_STATUS serviceStatus;

log("reportStatus: " + status); advapi32 = Advapi32.INSTANCE; serviceStatus = new WINSVC.SERVICE_STATUS(); serviceStatus.dwServiceType = WINNT.SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwControlsAccepted = WINSVC.SERVICE_ACCEPT_STOP; serviceStatus.dwWin32ExitCode = win32ExitCode; serviceStatus.dwWaitHint = waitHint; serviceStatus.dwCurrentState = status; advapi32.SetServiceStatus(serviceStatusHandle, serviceStatus); }

Service.java, Callbacks: private static class ServiceMain implements WINSVC.SERVICE_MAIN_FUNCTION { public void callback(int dwArgc, Pointer lpszArgv) { Advapi32 advapi32;

advapi32 = Advapi32.INSTANCE;

serviceControl = new ServiceControl(); serviceStatusHandle = advapi32.RegisterServiceCtrlHandler("MailService", serviceControl);

// reportStatus(WINSVC.SERVICE_START_PENDING, WINERROR.NO_ERROR, 3000); reportStatus(WINSVC.SERVICE_RUNNING, WINERROR.NO_ERROR, 0); } }

private static class ServiceControl implements WINSVC.HANDLER { public void callback(int fdwControl) { reportStatus(WINSVC.SERVICE_STOP_PENDING, WINERROR.NO_ERROR, 3000); log("ServiceControl: " + fdwControl); // this does not log anything reportStatus(WINSVC.SERVICE_STOP_PENDING, WINERROR.NO_ERROR, 3000); } }

Any hints would be greatly appreciated.