United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: 4323062 Any Windows NT Service embedding Java VM aborts, when user logs out from Windows
4323062 : Any Windows NT Service embedding Java VM aborts, when user logs out from Windows

Details
Type:
Bug
Submit Date:
2000-03-18
Status:
Closed
Updated Date:
2001-07-30
Project Name:
JDK
Resolved Date:
2000-11-16
Component:
hotspot
OS:
windows_nt,solaris_2.3,windows_2000
Sub-Component:
runtime
CPU:
x86,generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.2.2,1.2.2_006,1.3.0
Fixed Versions:
1.3.0_04

Related Reports
Backport:
Backport:
Duplicate:
Duplicate:
Relates:
Relates:
Relates:

Sub Tasks

Description
   IHAC with a NT Service program which starts a Java program. The java
 program is a simple program with a server socket waiting to accept socket
 connections. The program is installed and everything works fine until the user
 decides to log off. Since the Java program is installed through the NT Service,
 the program should continue to work even when the user logs out of the
 system. But on the contrary, the program goes into an unstable state and the
 program hangs. I have enclosed the stack trace which I managed to capture by
 making the NT Service interact with the desktop, so we get to see the console.

 This problem does not occur with JDK1.1.x. This happens only for JDK1.2 and
 greater versions. The Java thread dump and testcase TestNTSvc.tar.Z is
 in the attachments.
 

Follow these instructions to reproduce the problems:
SOURCE MODIFICATION
=============================================================
1)In the clienttest.java file edit line 16:
   s = new Socket("sworks.eng.sun.com",7990);
  with your test system's host address. Save and recompile. 


INSTRUCTIONS FOR INSTALLING SERVICE ON WINDOW NT 4.0
==============================================================

1. Extract the contents of the zip file to say C:\
2. Assuming this, you would now have a directory C:\testntsvc
3. Create an "System Variable" TEST_ROOT in Environment tab of the System
   Properties from the "Control Panel" Settings
and set C:\testntsvc
to
   TEST_ROOT.
4. Append C:\testntsvc to your classpath settings in control panel and also 
   make sure your CLASSPATH is a "System Variable". 
5. Go to DOS command prompt and go to the directory c:\testntsvc
6. Type TestNTSvc -install to install the NTService.
7. Now go to your control panel settings and click on the "Services"
   icon to see if the NT Service "TestNTSvc" is installed.
8. If it has not been installed please contact me at ###@###.###
or 650 526 3336.
9. If it has been installed, then select the "TestNTSvc"
in the services window, click on the button "Startup" and set
the "StartUp Type" to Manual(from Automatic). 
Also check the checkbox for "Allow Service to interact with the Desktop".
10. Now  click on OK Button and close the control panel settings.
11. Now ensure that you have installed JDK1.1.6, JDK1.1.7b and Java2 on your 
	NT Workstation.
12. Open the file "cmdscripts.cfg" file in C:\testntsvc, and update your
directory path for the various jre vms. You can comment all the lines
except the line which you intend to invoke a particular JVM, so for example
you intend to run jre1.2.2, then the following would be the text in the
file cmdscripts.cfg file:

================================================================================
adm=d:/jdk1.2.2/jre/bin/java -mx256m -DTEST_ROOT=%TEST_ROOT% testserver
#adm=f:/jdk1.1.7b/bin/java -mx256m -classpath %classpath%;f:/testntsvc -DTEST_ROOT=%TEST_ROOT% testserver
#adm=f:/jdk1.1.7b/bin/jre -mx256m -cp f:/testntsvc -DTEST_ROOT=%TEST_ROOT% testserver
adm=f:/jdk1.1.6/bin/jre -cp f:/testntsvc -DTEST_ROOT=%TEST_ROOT% testserver
#adm=f:/jdk1.1.6/bin/java -classpath %classpath%;f:/testntsvc -DTEST_ROOT=%TEST_ROOT% testserver
================================================================================
13. Save the file and close it.
14. Reboot your workstation so that the classpath and the new "System
variables" comes into effect.
15. After booting go to the control panel.
16. Go to the services panel in control panel and
start the NT Service "TestNTSvc". You should now see the Java console
for d:/jdk1.2.2/bin/jre with the statement "Getting Connected" being printed
in the console.

17. Run the Java test program testclient.java on the command prompt,
by typing in at the command prompt c:\testntsvc>java testclient
18. The program works and  exits normally after printing the statements
"Creating a Socket", "Created the client Socket" on the console. This 
is what a remote client system would see when accessing the Server service.

19. Now try logging off the NT Workstation and you will see in the Java console
    that the JVM dumps a Java thread trace and the service hangs unresponsive
    when you log back in.



Name: rlT66838			Date: 03/29/2000


java version "1.3.0rc2"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc2-Y)
Java HotSpot(TM) Client VM (build 1.3.0rc2-Y, mixed mode)


I'm writing NT-service by JDK1.3 (and some C codes).

1.NT-service start by manual. (check "System Account")
2.logoff

...then, NT-service(running JVM in service) stop process.

I hope, cancel shutdown JVM.
(Review ID: 103003)
======================================================================

Name: rlT66838			Date: 04/04/2000


java version "1.3.0rc1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0rc1-T)
Java HotSpot(TM) Client VM (build 1.3.0rc1-S, mixed mode)

Using ServiceInstaller 1.1 (http://www.kcmultimedia.com/smaster) install a
simple Java app as a service that outputs some trivial data to a file every
10 seconds.

Here's the simple demo service:

import java.io.*;
import java.util.*;


public class Test2
{
    public static void main(String[] args)
    {

        Date now;
        PrintWriter out;

        try{

            

            while(true){

                now = new Date();
                out = new PrintWriter(new FileWriter("test2.out",true), true);
                out.println(now.toString());
                out.close();

                Thread.sleep(10000);

            }

        }catch(Exception e){

            System.out.println(e.toString());

        }
    }
}

Start the service from the Control Panel|Services Applet, and check the
contents of the file test2.out, which should append a line showing the
date and time each 10 sec.

Log off, and log back in.

Although NT thinks the service is still running, it is not. You will see
that lines are no longer appended to the file.

This seems to only occur with JDK 1.3 RC1. Under JDK 1.2.2, the test app
keeps running thru the login/logout
(Review ID: 102993)
======================================================================

Name: yyT116575			Date: 11/09/2000


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)

I am using JNI 1.2 with JRE 1.3:

Write an NT Service that uses JNI to call the main method of a Java class
(NOTE user.name will be "SYSTEM")

Install & start the service.

Logoff.

Service dies!!!

NOTE:  JRE 1.2 deals with this correctly--when user logs back in the service is
still running.

I have thoroughly checked that my code is not exiting--
    env->CallStaticVoidMethod(jcl, m_methID, m_jobjArr);
never returns & there exists NO System.exit() in my java class.
(Review ID: 111892)
======================================================================

                                    

Comments
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
ladybird

FIXED IN:
ladybird

INTEGRATED IN:
1.3.0_04
ladybird
merlin-beta

VERIFIED IN:
1.3.0_04


                                     
2004-06-14
EVALUATION

It seems that this is not a bug.

In 1.1.x, runtime.exec create a new process which is a detached process, so the
child process will not accept signals (like ctrl+break) from the console of the 
parent process. That's why in 1.1.x, there's no thread dump. 

In 1.2.2, runtime.exec create a new attached process, the child process can 
still accept the signal from the console of the parent process, it's stderr is 
linked to the parent's pipe. After it received the signal, it sent out thread 
dump to stderr which redirects to the pipe, as the pipe has a limited capacity, 
another thread needs to read from the pipe to keep it going, otherwise, 
the child process appears hang.


###@###.### 2000-04-18

------------------------------------------------------------

The evaluation above is incorrect; a corrected one follows. A solution
exists for this problem; please see the end of this evaluation for it.

The problem was caused by the addition of the shutdown hook mechanism
to 1.3. Shutdown hooks, compared to the System.runFinalizersOnExit()
mechanism, have stronger guarantees regarding when they are run; for
example, if the VM is terminated by a Ctrl-C, finalizers will not be
executed via runFinalizersOnExit, but shutdown hooks will be run.

On Win32, shutdown hooks are implemented by adding a console control
handler (see the documentation for SetConsoleCtrlHandler) which, upon
seeing a condition like a Control-C or a "user logoff event", raises
the termination condition in the VM. This causes the shutdown hooks to
be run.

Both the shutdown hook mechanism and the Ctrl-Break stack dump require
signal-like information. 1.2 implemented the Ctrl-Break stack dump
using the POSIX "signal" call on Win32. It turns out (as was noted in
the 1.3 VM code by hong.zhang@eng) that this mechanism translates all
console events except Ctrl-C into SIGBREAK, which is not sufficient
granularity to support both Ctrl-Break and shutdown hooks. This is why
the console control handler was added in 1.3.

When the VM's console handler receives the CTRL_LOGOFF_EVENT, it
informs the rest of the VM of pending termination (thereby causing
shutdown hooks to be run) and returns TRUE. According to the MSDN
documentation, a return value of TRUE for this event will cause the
popup window for process termination to be displayed. It seems that
this return value was chosen because the VM is still doing work
(running the shutdown hooks asynchronously) after the
CTRL_LOGOFF_EVENT is received, and the author thought that returning
false would cause the VM to be terminated by the OS while doing this
work (as is stated in the MSDN documentation: the system's default
handler terminates the process).

The MSDN documentation is not specific about the relationship between
services and the CTRL_LOGOFF_EVENT. Conceptually, a service runs in
the background and should not be associated with any particular user's
login session, so one might expect that a service should not be
notified of logoff events. However, Win32 does send these events to
services. Interestingly, the default console handler for services
differs from the default for ordinary console processes; services
continue to run after their default handler executes. This is what
allows ordinary programs (which either do not install a console
handler, or which return FALSE in their console handler for
CTRL_LOGOFF_EVENT) to work with, for example, ServiceInstaller.
However, it does not seem that there is a way for a process to query
whether it is running as a service. If there were, the correct
behavior for the VM upon receiving the CTRL_LOGOFF_EVENT if it were
running as a service would be to skip running the shutdown hooks, not
signal the termination condition to the rest of the VM, and return
FALSE. Otherwise, the two possible workarounds are either to provide
another command line option to java.exe ("running as a service on
Windows NT") or to somehow intercept the CTRL_LOGOFF_EVENTs at the
service wrapper level.

--

Since the time this bug was filed, its original submitter (who is the
author of ServiceInstaller) has released a revised piece of software,
called JavaServ, which solves this problem elegantly by using the JNI
Invocation API to create a Java VM and installing a console control
handler afterwards which intercepts the CTRL_LOGOFF_EVENT and prevents
it from being passed to the VM. It also contains other useful features
like allowing pure Java programs to receive service control events.
JavaServ may be downloaded from

http://www.kcmultimedia.com/javaserv/

The comments on the JDC also contain the source code to a similar
program.

kenneth.russell@eng 2000-08-30

-----------------------------------------------------------------

Since the time the above evaluation was written, other problems have
been discovered on Unix platforms involving the interaction between
the signals/events the VM now catches to implement the shutdown hook
mechanism and application code which may rely on catching those
signals; see bug 4345157 and related bugs. It was agreed that it is
necessary to have a cross-platform mechanism to inform the VM that the
user will take care of calling shutdown hooks (by calling
System.exit()), but because he/she either needs to catch SIGINT or
similar signals on Unix or run the VM as a service on NT, the VM must
not install signal handlers or attempt to catch console control
events. It appears that similar reasoning informed the addition of the
-Xrs flag in the Classic VM.

The -Xrs flag has been reused to support this functionality; if it is
specified on Windows NT, for example, java.exe can again be run with
the ServiceInstaller wrapper (http://www.kcmultimedia.com/smaster/).
This fix will appear in 1.3.1 and be documented in the README.

kenneth.russell@eng 2000-11-08
                                     
2000-11-08
WORK AROUND

The workaround is to create a new thread in the parent process to read the pipe.
In this way, the pipe between the parent and child process will not get overflowed. The application will not hang any more. Also if the return value 
from read is -1, the read thread may be dismissed to retain resources.

###@###.### 2000-06-02
                                     
2000-06-02



Hardware and Software, Engineered to Work Together