Wed 02 Mar 2011 10:31:18 AM UTC, original submission:
<--BEGIN description-->
According to Simon:
"The old PPP code was really broken regarding multithreading. The modifications() that were necessary include that none* of the PPP functions may be called from any other thread than the tcpip_thread".
(*) modifications refer to version 1.4.0
When adjusting our code to call PPP APIs (pppOverSerialOpen, pppSigHup, pppClose) using tcpip_callback_with_block(), PPP code started crashing upon link termination.
<--END description-->
<--BEGIN our analysis-->
"pppLinkTerminated is always called after lcp phase is set to PHASE_DEAD. In it, the pppInput thread is "released" by calling pppRecvWakeup, the application callback is called with PPPERR_PROTOCOL, and openFlag is set to 0.
Since PPP does not manage the sio_fd (it simply receives an open handle and does not close it), there must be a point in which PPP lets me know I can have my sio_fd back. This point AFAICT is when my link_status_cb is called with PPPERR_PROTOCOL.
The problem (the crash actually) occurs because both pppClose and pppHup call pppRecvWakeup AFTER calling pppLinkTerminated. Since I release my resources on pppLinkTerminated, the call to pppRecvWakeup references a nonexistent sio_fd object.
Ideally this sio_fd would simply be an invalid handle (which is why I did not report this as a crash error), but in our case it is a real pointer.
<--END our analysis-->
<--BEGIN our fix-->
1. Removed the pppRecvWakeup() call from pppSigHup()
2. Added a conditional to pppRecvWakeup() -
if (pppControl[pd].openFlag)
sio_read_abort(pppControl[pd].fd);
<--END our fix-->
NOTE: have not checked against original ppp code.
|