Bug 235 - Application DoDispose methods can be called after all the channels are deleted
Application DoDispose methods can be called after all the channels are deleted
Status: RESOLVED FIXED
Product: ns-3
Classification: Unclassified
Component: internet
pre-release
All All
: P1 normal
Assigned To: ns-bugs
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2008-06-24 16:33 UTC by Rajib Bhattacharjea
Modified: 2008-07-01 13:32 UTC (History)
1 user (show)

See Also:


Attachments
toy http model demostrating the problem (19.82 KB, patch)
2008-06-24 16:34 UTC, Rajib Bhattacharjea
Details | Diff
fix (387 bytes, patch)
2008-06-24 17:59 UTC, Rajib Bhattacharjea
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Rajib Bhattacharjea 2008-06-24 16:33:42 UTC
The removal of the socket-to-application close notifications has lead applications to close their sockets upon invocation of their DoDispose method at Simulator::Destroy time.  It appears to me that in some cases, the order of Dispose calls is such that the channels are gone and deleted before an Application subclass's DoDispose is hit.  In the case of TCP, the socket close (called from an Application DoDispose) does something, it can send a FIN packet, but the channel can be gone from under it since it was disposed of earlier.

I have a fairly simple test case that cloned the PacketSink and OnOff to make WebServer and WebClient respectively.
Comment 1 Rajib Bhattacharjea 2008-06-24 16:34:55 UTC
Created attachment 180 [details]
toy http model demostrating the problem

./waf --run=simple-http
Comment 2 Rajib Bhattacharjea 2008-06-24 16:51:51 UTC
It segfaults in the point-to-point channel code.  Here is a stack trace:

#0  0xb7d4b0bc in ns3::PointToPointChannel::TransmitStart (this=0x0, p=@0xbf82b228, src=@0xbf82b224, txTime=@0xbf82b1f4)
    at ../src/devices/point-to-point/point-to-point-channel.cc:87
#1  0xb7d445c5 in ns3::PointToPointNetDevice::TransmitStart (this=0x80643d0, p=@0xbf82b27c)
    at ../src/devices/point-to-point/point-to-point-net-device.cc:161
#2  0xb7d45747 in ns3::PointToPointNetDevice::Send (this=0x80643d0, packet=@0xbf82b3c8, dest=@0xbf82b44c, protocolNumber=2048)
    at ../src/devices/point-to-point/point-to-point-net-device.cc:429
#3  0xb7d03710 in ns3::ArpIpv4Interface::SendTo (this=0x8064620, p=@0xbf82b4a4, dest={m_address = 167837954})
    at ../src/internet-stack/arp-ipv4-interface.cc:152
#4  0xb7ccc61a in ns3::Ipv4Interface::Send (this=0x8064620, p=@0xbf82b5b0, dest={m_address = 167837954})
    at ../src/internet-stack/ipv4-interface.cc:169
#5  0xb7cd2386 in ns3::Ipv4L3Protocol::SendRealOut (this=0x8063d38, found=true, route=@0x8066070, packet=@0xbf82b61c, 
    ipHeader=@0xbf82bac8) at ../src/internet-stack/ipv4-l3-protocol.cc:601
#6  0xb7cdfb30 in ns3::MemPtrCallbackImpl<ns3::Ipv4L3Protocol*, void (ns3::Ipv4L3Protocol::*)(bool, ns3::Ipv4Route const&, ns3::Ptr<ns3::Packet>, ns3::Ipv4Header const&), void, bool, ns3::Ipv4Route const&, ns3::Ptr<ns3::Packet>, ns3::Ipv4Header const&, ns3::empty, ns3::empty>::operator() (this=0x806ea48, a1=true, a2=@0x8066070, a3=@0xbf82b658, a4=@0xbf82bac8)
    at debug/ns3/callback.h:211
#7  0xb7cdfbc6 in ns3::Callback<void, bool, ns3::Ipv4Route const&, ns3::Ptr<ns3::Packet>, ns3::Ipv4Header const&, ns3::empty, ns3::empty>::operator() (this=0xbf82b8c8, a1=true, a2=@0x8066070, a3=@0xbf82b794, a4=@0xbf82bac8) at debug/ns3/callback.h:376
#8  0xb7ce6f7a in ns3::Ipv4StaticRouting::RequestRoute (this=0x8063d90, ifIndex=4294967295, ipHeader=@0xbf82bac8, 
    packet=@0xbf82b8cc, routeReply=@0xbf82b8c8) at ../src/internet-stack/ipv4-static-routing.cc:562
#9  0xb7cd4832 in ns3::Ipv4L3Protocol::Lookup (this=0x8063d38, ifIndex=4294967295, ipHeader=@0xbf82bac8, packet=@0xbf82b9c8, 
    routeReply=@0xbf82b9c4) at ../src/internet-stack/ipv4-l3-protocol.cc:209
#10 0xb7cd6ae2 in ns3::Ipv4L3Protocol::Lookup (this=0x8063d38, ipHeader=@0xbf82bac8, packet=@0xbf82bb14, routeReply=@0xbf82bb10)
    at ../src/internet-stack/ipv4-l3-protocol.cc:191
#11 0xb7cd7322 in ns3::Ipv4L3Protocol::Send (this=0x8063d38, packet=@0xbf82bc10, source={m_address = 167837953}, destination=
      {m_address = 167837954}, protocol=6 '\006') at ../src/internet-stack/ipv4-l3-protocol.cc:573
#12 0xb7cede18 in ns3::TcpL4Protocol::SendPacket (this=0x8063f50, packet=@0xbf82be1c, outgoingHeader=@0xbf82bdf0, saddr=
      {m_address = 167837953}, daddr={m_address = 167837954}) at ../src/internet-stack/tcp-l4-protocol.cc:519
#13 0xb7d23066 in ns3::TcpSocketImpl::SendEmptyPacket (this=0x806e1e8, flags=1 '\001')
    at ../src/internet-stack/tcp-socket-impl.cc:647
#14 0xb7d248ea in ns3::TcpSocketImpl::ProcessAction (this=0x806e1e8, a=ns3::FIN_TX)
    at ../src/internet-stack/tcp-socket-impl.cc:698
#15 0xb7d26d9b in ns3::TcpSocketImpl::Close (this=0x806e1e8) at ../src/internet-stack/tcp-socket-impl.cc:306
#16 0xb7d65778 in ns3::WebServer::DoDispose (this=0x80660e0) at ../src/applications/http/web-server.cc:72
#17 0xb7b7798f in ns3::Object::Dispose (this=0x80660e0) at ../src/core/object.cc:131
#18 0xb7c885f0 in ns3::Node::DoDispose (this=0x8063940) at ../src/node/node.cc:147
#19 0xb7b7798f in ns3::Object::Dispose (this=0x8063940) at ../src/core/object.cc:131
#20 0xb7ca909f in ~NodeListPriv (this=0x8063980) at ../src/node/node-list.cc:109
#21 0xb7b77494 in ns3::Object::MaybeDelete (this=0x8063980) at ../src/core/object.cc:240
#22 0x0804e187 in ns3::Object::Unref (this=0x8063980) at debug/ns3/object.h:336
#23 0xb7cabb34 in ns3::Ptr<ns3::NodeListPriv>::operator= (this=0xb7fe03d8, o=@0xbf82c178) at debug/ns3/ptr.h:421
#24 0xb7caab06 in ns3::NodeListPriv::Delete () at ../src/node/node-list.cc:94
#25 0xb7bfcf96 in Notify (this=0x80639b0) at ../src/simulator/simulator.cc:518
#26 0xb7bfceae in ns3::EventImpl::Invoke (this=0x80639b0) at ../src/simulator/event-impl.cc:39
#27 0xb7c04876 in ns3::SimulatorPrivate::Destroy (this=0x80639c8) at ../src/simulator/simulator.cc:159
#28 0xb7c0490e in ns3::Simulator::Destroy () at ../src/simulator/simulator.cc:460
#29 0x0804d4dc in main (argc=1, argv=0xbf82c5e4) at ../examples/simple-http.cc:135
Comment 3 Rajib Bhattacharjea 2008-06-24 17:59:24 UTC
Created attachment 181 [details]
fix

To summarize some IRC discussion, we decided that as a policy, calling any code other than memory management cleanup in DoDispose is not allowed.  This shifts the responsibility of closing sockets to the application before Simulator::Destroy time, i.e. it should have closed down the socket before we got to DoDispose, and the simulator will shutdown as gracefully as possible in this circumstance by just releasing its reference to the socket.

This fix is for the PacketSink, as it calls Socket::Close from its DoDispose.  This fixes an underlying issue related to my problem.