My crash occurs when I reset a timer when a new tcp connection is accepted.
The timer is created with this class:
Code: Select all
class c_interval // interval timer based on TimeTick
{
public:
volatile DWORD start_time, timeout, interval;
explicit c_interval(DWORD msec=1000); // interval in msec.
void Reset(DWORD msec=0); // If parameter not supplied, interval is left alone.
bool Cycle(DWORD msec=0); // If time has expired, returns true and increments by one interval.
bool Expired(); // If time has expired, returns true.
DWORD ElapsedSec();
DWORD ElapsedMsec();
DWORD RemainingSec();
void ForceExpiration(); // sets start_time such that Cycle() or Expired() will return true.
};
There is a tcp connection class where this timer is used to close tcp connections
when there is no activity for a certain amount of time. See "idle" parameter.
Note that the only change to this class is changing ip_addr from IPADDR4 to IPADDR.
Code: Select all
class protocol_link
{
public:
int port;
char rbuf[PROTOCOL_BUF_SIZE]; // holds incoming packet.
char tbuf[PROTOCOL_BUF_SIZE]; // holds outgoing packet.
int count; // size of current packet.
char address;
bool printable, check_address, efd_protocol;
bool udp_redirect; // TRUE = this is a redirect of UDP-compatible messaging.
int efd_addr;
enum_packet_state step;
#ifdef IPv6_DEVELOPMENT
IPADDR ip_addr; // The ip address of the remote host, if applicable.
#else
IPADDR4 ip_addr; // The ip address of the remote host, if applicable.
#endif
bool running; // prevent recursion, ex: block routines triggered by current packet from checking for another packet...
// ... and upon seeing the same packet (having not called ResetLink()), go into infinite loop.
c_interval *idle; // idle timer, restarted by ResetLink()
protocol_link():port(-1),count(0),address('A'),printable(false),check_address(false),efd_protocol(false),
udp_redirect(false),efd_addr(1),step(PACKET_DEFAULT_STATE),running(false)
{
idle = new c_interval(300000); // 300,000 msec = 5 minutes
rbuf[0] = 0;
tbuf[0] = 0;
}
~protocol_link() { delete [] idle; }
void Init(int fd, char device_address, bool check_address, bool as_udp=false);
int Send(char start_char, const char *string, char new_address=0, int send_bytes=-1);
int Printf(char start_char, const char *format_str, ...);
protocol_status_enum Receive();
protocol_status_enum ReceiveUdp();
char CheckSum(char *buf, int size);
void Reset(), ResetLink();
void KillCheckSum(); // zeroes rbuf[] checksum field, typically called AFTER confirming the checksum (if applicable).
};
When a new tcp connection is established, the function protocol_link::ResetLink()
is called, and it in turn calls c_interval::Reset() to restart the timer. It's resetting
the timer where it crashes.
This is the reset function:
Code: Select all
void c_interval::Reset(DWORD msec)
{
if (msec) interval = (DWORD)(msec * TICKS_PER_SECOND / 1000); //lint !e790 Example: 50 msec interval x 20 ticks/sec / 1000 = 1 tick.
timeout = TimeTick + interval; //lint !e644
start_time = TimeTick;
}
This is the assembly code of the Reset() function. The crash always happens at address 4004138, which
appears to be when the code assigns a value to timeout.
Code: Select all
40041708 <_ZN10c_interval5ResetEm>:
40041708: 4e56 0000 linkw %fp,#0
4004170c: 206e 0008 moveal %fp@(8),%a0
40041710: 2f02 movel %d2,%sp@-
40041712: 202e 000c movel %fp@(12),%d0
40041716: 6714 beqs 4004172c <_ZN10c_interval5ResetEm+0x24>
40041718: 7214 moveq #20,%d1
4004171a: 4c01 0800 mulsl %d1,%d0
4004171e: 243c 0000 03e8 movel #1000,%d2
40041724: 4c42 0000 remul %d2,%d0,%d0
40041728: 2140 0008 movel %d0,%a0@(8)
4004172c: 2028 0008 movel %a0@(8),%d0
40041730: 2239 8000 09e8 movel 800009e8 <TimeTick>,%d1
40041736: d081 addl %d1,%d0
40041738: 2140 0004 movel %d0,%a0@(4)
4004173c: 2039 8000 09e8 movel 800009e8 <TimeTick>,%d0
40041742: 241f movel %sp@+,%d2
40041744: 2080 movel %d0,%a0@
40041746: 4e5e unlk %fp
40041748: 4e75 rts
This is how the connection is accepted.
Code: Select all
protocol_link mandc[TOTAL_PROTOCOL_LINKS]; // total links = 12
int listener = listen( INADDR_ANY, (WORD) port, 1 );
...
void ManageTcp()
{
IPADDR addr;
if ( !IsSocketReadable( listener ) ) return; // Readability on a listening socket = connection available.
int fd = accept( listener, &addr, NULL, 0 ); // blocking call but allegedly a connection is available.
if ( fd <= 0 ) return; // if not valid file descriptor, bail...
// look for available socket...
for ( i = 0; i < TOTAL_PROTOCOL_LINKS; i++ )
{
if ( mandc[i].port < 0 ) // available link.
{
mandc[i].port = fd; // aka the socket.
mandc[i].ip_addr = addr; <---- Is this corrupting memory!!!
mandc[i].ResetLink(); <---- CRASH
setsockoption( mandc[i].port, SO_NONAGLE );
break;
}
}
}
static bool IsSocketReadable( int fd )
{
static fd_set fds_list;
FD_ZERO( &fds_list ); // reset file descriptor list.
FD_SET( fd, &fds_list ); // add us to list, to be checked for readability.
return ZeroWaitSelect( FD_SETSIZE, &fds_list, NULL, NULL ) != 0; // check for readability and return immediately.
}
Is memory being corrupted when the IP address is saved?