From: Patrick B. <pat...@jo...> - 2011-11-03 20:03:12
|
Hi everyone, In my stress testing I've found a deadlock issue that in the XQuery Update code, it's in Modification.selectAndLock(..) on line 147. The problem was that a READ_LOCK was being acquired on the BrokerPool inside of the try/finally that removed it. So, in the case the acquire failed and threw an error, the release would pop off the wrong READ_LOCK. If one of the core developers is good with my change, I'll commit it into the stable/1.4.x branch Was: protected StoredNode[] selectAndLock(Txn transaction, Sequence nodes) throws LockException, PermissionDeniedException, XPathException { Lock globalLock = context.getBroker().getBrokerPool().getGlobalUpdateLock(); try { globalLock.acquire(Lock.READ_LOCK); lockedDocuments = nodes.getDocumentSet(); // acquire a lock on all documents // we have to avoid that node positions change // during the modification lockedDocuments.lock(context.getBroker(), true, false); StoredNode ql[] = new StoredNode[nodes.getItemCount()]; for (int i = 0; i < ql.length; i++) { Item item = nodes.itemAt(i); if (!Type.subTypeOf(item.getType(), Type.NODE)) throw new XPathException(this, "XQuery update expressions can only be applied to nodes. Got: " + item.getStringValue()); NodeValue nv = (NodeValue)item; if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) throw new XPathException(this, "XQuery update expressions can not be applied to in-memory nodes."); Node n = nv.getNode(); if (n == null) throw new XPathException(this, "Internal error: node to update is null"); if (n.getNodeType() == Node.DOCUMENT_NODE) throw new XPathException(this, "Updating the document object is not allowed."); ql[i] = (StoredNode) n; DocumentImpl doc = (DocumentImpl)ql[i].getOwnerDocument(); //prepare Trigger try { prepareTrigger(transaction, doc); } catch (TriggerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return ql; } finally { globalLock.release(Lock.READ_LOCK); } } Changed to: (moved lock out of try) protected StoredNode[] selectAndLock(Txn transaction, Sequence nodes) throws LockException, PermissionDeniedException, XPathException { Lock globalLock = context.getBroker().getBrokerPool().getGlobalUpdateLock(); globalLock.acquire(Lock.READ_LOCK); try { lockedDocuments = nodes.getDocumentSet(); // acquire a lock on all documents // we have to avoid that node positions change // during the modification lockedDocuments.lock(context.getBroker(), true, false); StoredNode ql[] = new StoredNode[nodes.getItemCount()]; for (int i = 0; i < ql.length; i++) { Item item = nodes.itemAt(i); if (!Type.subTypeOf(item.getType(), Type.NODE)) throw new XPathException(this, "XQuery update expressions can only be applied to nodes. Got: " + item.getStringValue()); NodeValue nv = (NodeValue)item; if (nv.getImplementationType() == NodeValue.IN_MEMORY_NODE) throw new XPathException(this, "XQuery update expressions can not be applied to in-memory nodes."); Node n = nv.getNode(); if (n == null) throw new XPathException(this, "Internal error: node to update is null"); if (n.getNodeType() == Node.DOCUMENT_NODE) throw new XPathException(this, "Updating the document object is not allowed."); ql[i] = (StoredNode) n; DocumentImpl doc = (DocumentImpl)ql[i].getOwnerDocument(); //prepare Trigger try { prepareTrigger(transaction, doc); } catch (TriggerException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return ql; } finally { globalLock.release(Lock.READ_LOCK); } } -- Patrick Bosek Jorsek Software Cell (585) 820 9634 Office (877) 492 2960 Jorsek.com |