Skip to content

Conversation

@scw00
Copy link
Member

@scw00 scw00 commented Feb 21, 2019

Based on #4873, The ua_txn set to nullptr, transaction_done is never called by HttpSM. So the Session is never freed.

@scw00 scw00 added the HTTP label Feb 21, 2019
@scw00 scw00 added this to the 9.0.0 milestone Feb 21, 2019
@scw00 scw00 self-assigned this Feb 21, 2019
@scw00
Copy link
Member Author

scw00 commented Feb 21, 2019

link to #5042

@oknet
Copy link
Member

oknet commented Feb 21, 2019

As the state machine implementer,

  • once the state machine has finished using this VConnection, the state machine must call do_io_close to indicate that the VConnection can be deallocated.
  • the state machine must not access the VConnection or any VIOs obtained from it after calling this method.

As the underlying processor implementer,

  • after a close has been called, the underlying processor must not send any more events related to this VConnection to the state machine.

Setting the ua_txn to nullptr is right thing. We should review the design of transaction_done if this makes any mistake.

The comments in I_VConnection.h for VConnection::do_io_close:

256   /**
257     Indicate that the VConnection is no longer needed.
258 
259     Once the state machine has finished using this VConnection, it
260     must call this function to indicate that the VConnection can
261     be deallocated.  After a close has been called, the VConnection
262     and underlying processor must not send any more events related
263     to this VConnection to the state machine. Likeswise, the state
264     machine must not access the VConnection or any VIOs obtained
265     from it after calling this method.
266 
267     @param lerrno indicates where a close is a normal close or an
268       abort. The difference between a normal close and an abort
269       depends on the underlying type of the VConnection.
270 
271   */
272   virtual void do_io_close(int lerrno = -1) = 0;

@SolidWallOfCode
Copy link
Member

I think I agree with @oknet - the call to do_io_close should suffice to clean up. If not, we need to look at that. Having a dangling VConn that's been closed is unlikely to end well.

@shinrich
Copy link
Member

shinrich commented Feb 21, 2019

We call transcation_done from the HttpSM::kill_this() to allow for the TXN_CLOSE hook to be called at the proper end of the transaction. As I recall, trying to trigger the TXN_CLOSE hooks from the ProxyTransaction::do_io_close() was problematic. There were cases when the transaction wasn't quite done.

The ua_txn->do_io_close() will shutdown the VConnection associated with the user agent and null out the reference, so there is no dangling VConnection. However, we still need the ProxyTransaction object (ua_txn), so we can signal TXN_CLOSE when the HttpSM is really shut down.

In my opinion, the proposed fix is good.

@duke8253
Copy link
Contributor

Nice, was planning on looking at this issue.

@masaori335
Copy link
Contributor

For workaround fix, I'm fine with this. But I agree with oknet, we should revisit design of ProxyTransaction and VConnection.

@scw00
Copy link
Member Author

scw00 commented Feb 22, 2019

Let’s open an issue to trace this case.

@scw00
Copy link
Member Author

scw00 commented Feb 22, 2019

link to #5052

@SolidWallOfCode
Copy link
Member

@shinrich talked to me about this, and convinced me this is the correct approach. The key point was the ua_txn object serves as an intermediary between the HttpSM and the NetVC. It is expected to handle doing the NetVC cleanup, the HttpSM shouldn't get involved. The transaction object will handle not touching the NetVC again, the HttpSM should just trust it to do the right thing. The point here, by @scw00, is that it is this transaction object that is getting leaked, not the NetVC.

@scw00
Copy link
Member Author

scw00 commented Feb 23, 2019

Yes, I introduced remove_entry because the NetVC will be destroyed after we return back to NetHandler. And the HttpSM::kill_this should not access vio anymore (in HttpSM::kill_this ----->vc_table.cleanup_all) .

Is it possible to do ProxyTransaction as a VConnection ? As the comment said "* the state machine must not access the VConnection or any VIOs obtained from it after calling this method."

class HttpSM;
class HttpServerSession;
class ProxyClientTransaction : public VConnection
{
public:
  ProxyClientTransaction();

  // do_io methods implemented by subclasses

  virtual void new_transaction();

  virtual NetVConnection *
  get_netvc() const
  {
    return (parent) ? parent->get_netvc() : nullptr;
  }

@scw00
Copy link
Member Author

scw00 commented Feb 27, 2019

I will merge this PR if there is no objection.

@shinrich
Copy link
Member

+1 on the merge.

In terms of the concern about the semantics of ::do_io_close on the ua_txn object. Would it be clearer and more consistent if we named that function ::release instead so there was no expectation that the ua_txn object was inaccessible after the call? So

ua_txn->release() (which would still call do_io_close on the underlying netvc)

@scw00
Copy link
Member Author

scw00 commented Feb 28, 2019

IIUC, class ProxyClientTransaction : public VConnection means we can pass ProxyClientTransaction as VConnection directly (we don't use it in current logic).

When some one want to call VConnection::do_io_close it doesn't call transaction_done because there is no transaction_done in VConnection.

IIUC, do_io_close means close txn directly that means the session is terminated and it will not create a new transaction any more and will be destroyed after (or before) client's connection closed.

release means keep alive. That Session is waiting for next request and create a new transaction for that request.

I think these are different semantics.

@scw00 scw00 merged commit 5e2d175 into apache:master Feb 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants