java - Does WebSphere 7 HTTPSession implementation contravene J2EE spec? -



java - Does WebSphere 7 HTTPSession implementation contravene J2EE spec? -

saw problem 200 web container threads became hung, meaning none available service incoming requests , application froze.

here simple web app , jmeter test think demonstrates cause of problem. web app consists of 2 classes, next servlet:

public class sessiontestservlet extends httpservlet { protected static final string session_key = "session_key"; protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { // set info on session listener invoked string sessiondata = new string("session data"); request.getsession().setattribute(session_key, sessiondata); printwriter author = response.getwriter(); writer.println("<html><body>ok</body></html>"); writer.flush(); writer.close(); } }

and next implementation of httpsessionlistener , httpsessionattributelistener:

public class sessiontestlistener implements httpsessionlistener, httpsessionattributelistener { private static final concurrentmap<string, httpsession> allsessions = new concurrenthashmap<string, httpsession>(); public void attributeremoved(httpsessionbindingevent hsbe) {} public void attributeadded(httpsessionbindingevent hsbe) { system.out.println("attribute added, " + hsbe.getname() + "=" + hsbe.getvalue()); int count = 0; (httpsession session : allsessions.values()) { if (session.getattribute(sessiontestservlet.session_key) != null) { count++; } } system.out.println(count + " of " + allsessions.size() + " sessions have attribute set."); } public void attributereplaced(httpsessionbindingevent hsbe) {} public void sessioncreated(httpsessionevent hse) { allsessions.put(hse.getsession().getid(), session); } public void sessiondestroyed(httpsessionevent hse) { allsessions.remove(hse.getsession().getid()); } }

the jmeter test has 100 requests nail servlet every second:

<?xml version="1.0" encoding="utf-8"?> <jmetertestplan version="1.2" properties="2.1"> <hashtree> <testplan guiclass="testplangui" testclass="testplan" testname="test plan" enabled="true"> <stringprop name="testplan.comments"></stringprop> <boolprop name="testplan.functional_mode">false</boolprop> <boolprop name="testplan.serialize_threadgroups">false</boolprop> <elementprop name="testplan.user_defined_variables" elementtype="arguments" guiclass="argumentspanel" testclass="arguments" testname="user defined variables" enabled="true"> <collectionprop name="arguments.arguments"/> </elementprop> <stringprop name="testplan.user_define_classpath"></stringprop> </testplan> <hashtree> <threadgroup guiclass="threadgroupgui" testclass="threadgroup" testname="thread group" enabled="true"> <stringprop name="threadgroup.on_sample_error">continue</stringprop> <elementprop name="threadgroup.main_controller" elementtype="loopcontroller" guiclass="loopcontrolpanel" testclass="loopcontroller" testname="loop controller" enabled="true"> <boolprop name="loopcontroller.continue_forever">false</boolprop> <intprop name="loopcontroller.loops">-1</intprop> </elementprop> <stringprop name="threadgroup.num_threads">100</stringprop> <stringprop name="threadgroup.ramp_time">1</stringprop> <longprop name="threadgroup.start_time">1327193422000</longprop> <longprop name="threadgroup.end_time">1327193422000</longprop> <boolprop name="threadgroup.scheduler">false</boolprop> <stringprop name="threadgroup.duration"></stringprop> <stringprop name="threadgroup.delay"></stringprop> </threadgroup> <hashtree> <httpsamplerproxy guiclass="httptestsamplegui" testclass="httpsamplerproxy" testname="http request" enabled="true"> <elementprop name="httpsampler.arguments" elementtype="arguments" guiclass="httpargumentspanel" testclass="arguments" testname="user defined variables" enabled="true"> <collectionprop name="arguments.arguments"/> </elementprop> <stringprop name="httpsampler.domain">localhost</stringprop> <stringprop name="httpsampler.port">9080</stringprop> <stringprop name="httpsampler.connect_timeout"></stringprop> <stringprop name="httpsampler.response_timeout"></stringprop> <stringprop name="httpsampler.protocol">http</stringprop> <stringprop name="httpsampler.contentencoding"></stringprop> <stringprop name="httpsampler.path">/session_testweb/sessiontestservlet</stringprop> <stringprop name="httpsampler.method">get</stringprop> <boolprop name="httpsampler.follow_redirects">true</boolprop> <boolprop name="httpsampler.auto_redirects">false</boolprop> <boolprop name="httpsampler.use_keepalive">true</boolprop> <boolprop name="httpsampler.do_multipart_post">false</boolprop> <boolprop name="httpsampler.monitor">false</boolprop> <stringprop name="httpsampler.embedded_url_re"></stringprop> </httpsamplerproxy> <hashtree> <constanttimer guiclass="constanttimergui" testclass="constanttimer" testname="constant timer" enabled="true"> <stringprop name="constanttimer.delay">1000</stringprop> </constanttimer> <hashtree/> </hashtree> </hashtree> <resultcollector guiclass="viewresultsfullvisualizer" testclass="resultcollector" testname="view results tree" enabled="true"> <boolprop name="resultcollector.error_logging">false</boolprop> <objprop> <name>saveconfig</name> <value class="samplesaveconfiguration"> <time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <message>true</message> <threadname>true</threadname> <datatype>true</datatype> <encoding>false</encoding> <assertions>true</assertions> <subresults>true</subresults> <responsedata>false</responsedata> <samplerdata>false</samplerdata> <xml>true</xml> <fieldnames>false</fieldnames> <responseheaders>false</responseheaders> <requestheaders>false</requestheaders> <responsedataonerror>false</responsedataonerror> <saveassertionresultsfailuremessage>false</saveassertionresultsfailuremessage> <assertionsresultstosave>0</assertionsresultstosave> <bytes>true</bytes> </value> </objprop> <stringprop name="filename"></stringprop> </resultcollector> <hashtree/> <resultcollector guiclass="summaryreport" testclass="resultcollector" testname="summary report" enabled="true"> <boolprop name="resultcollector.error_logging">false</boolprop> <objprop> <name>saveconfig</name> <value class="samplesaveconfiguration"> <time>true</time> <latency>true</latency> <timestamp>true</timestamp> <success>true</success> <label>true</label> <code>true</code> <message>true</message> <threadname>true</threadname> <datatype>true</datatype> <encoding>false</encoding> <assertions>true</assertions> <subresults>true</subresults> <responsedata>false</responsedata> <samplerdata>false</samplerdata> <xml>true</xml> <fieldnames>false</fieldnames> <responseheaders>false</responseheaders> <requestheaders>false</requestheaders> <responsedataonerror>false</responsedataonerror> <saveassertionresultsfailuremessage>false</saveassertionresultsfailuremessage> <assertionsresultstosave>0</assertionsresultstosave> <bytes>true</bytes> </value> </objprop> <stringprop name="filename"></stringprop> </resultcollector> <hashtree/> </hashtree> </hashtree> </jmetertestplan>

when test run against test web app deployed on websphere 7, application stops responding , core dump shows this:

1lkdeadlock deadlock detected !!! null --------------------- null 2lkdeadlockthr thread "webcontainer : 2" (0x000000000225c600) 3lkdeadlockwtr waiting for: 4lkdeadlockmon sys_mon_t:0x00000000151938c0 infl_mon_t: 0x0000000015193930: 4lkdeadlockobj com/ibm/ws/session/store/memory/memorysession@00000000a38ea0c8/00000000a38ea0d4: 3lkdeadlockown owned by: 2lkdeadlockthr thread "webcontainer : 1" (0x00000000021fb500) 3lkdeadlockwtr waiting for: 4lkdeadlockmon sys_mon_t:0x0000000015193820 infl_mon_t: 0x0000000015193890: 4lkdeadlockobj com/ibm/ws/session/store/memory/memorysession@00000000a14e22c0/00000000a14e22cc: 3lkdeadlockown owned by: 2lkdeadlockthr thread "webcontainer : 2" (0x000000000225c600) null

it appears when thread (t1) executing servlet's doget() method calls setattribute() on instance of httpsession implementation (s1), locks on monitor of s1. while holding lock goes iteration of allsessions within listener's attributeadded() method , calls getattribute(). looks within getattribute(), websphere locks on instance's monitor (possibly because setting lastupdatetime field?). so, t1 in turn lock monitors of s1, s2, s3, s4, s5... while holding lock on s1 setattribute() phone call in servlet.

so if @ same time thread (t2) locking on session (s2)'s monitor in servlet , goes loop in addattribute(), threads deadlock on s1 , s2 monitors.

i have been unable find explicit in j2ee specs part of servlet 2.4 spec implies container should not synchronizing on instances of httpsession implementations:

srv.7.7.1 threading issues

multiple servlets executing request threads may have active access single session object @ same time. developer has responsibility synchronizing access session resources appropriate.

jboss not show deadlocks when run test against it. questions are:

is understanding correct? if so, bug or contravention of j2ee spec in websphere? if not, , valid behaviour developer should know , code around, behaviour documented anywhere?

thanks

the servlet 2.5 mr6 contains clarification part of servlet spec quoted in question:

clarify srv 7.7.1 "threading issues" (issue 33)

change paragraph

"multiple servlets executing request threads may have active access single session object @ same time. developer has responsibility synchronizing access session resources appropriate."

to read

"multiple servlets executing request threads may have active access same session object @ same time. container must ensure manipulation of internal info structures representing session attributes performed in threadsafe manner. developer has responsibility threadsafe access attribute objects themselves. protect attribute collection within httpsession object concurrent access, eliminating chance application cause collection become corrupted."

this still current in servlet 3.0 mr1 , makes was's behaviour more reasonable. however, take *set*attribute might synchronized not *get*attribute be.

so think reply is:

was is complying servlet spec according clarification in 2.5 mr6 the spec leaves room misunderstanding was more zealous synchronization reasonably expected spec , afaik behaviour not documented anywhere

(as side note, changing test case listener.attributeadded() calls setattribute instead of getattribute doesn't cause deadlocks on jboss 4 or 5.)

java java-ee websphere deadlock

Comments

Popular posts from this blog

How do I check if an insert was successful with MySQLdb in Python? -

delphi - blogger via idHTTP : error 400 bad request -

postgresql - ERROR: operator is not unique: unknown + unknown -