wxldserv.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 // Name:        wxldserv.cpp
00003 // Purpose:     Provide remote debugging support for wxLua.
00004 // Author:      J. Winwood, John Labenski, Ray Gilbert
00005 // Created:     May 2002.
00006 // Copyright:   (c) 2002 Lomtick Software. All rights reserved.
00007 // Licence:     wxWidgets licence
00008 /////////////////////////////////////////////////////////////////////////////
00009 
00010 #include "wx/wxprec.h"
00011 
00012 #ifdef __BORLANDC__
00013     #pragma hdrstop
00014 #endif
00015 
00016 #ifndef WX_PRECOMP
00017     #include "wx/wx.h"
00018 #endif
00019 
00020 #include "wx/thread.h"
00021 #include "wxluasocket/include/wxldserv.h"
00022 #include "wxluadebug/include/wxlstack.h"
00023 
00024 #if !wxCHECK_VERSION(2, 6, 0)
00025     #define wxMilliSleep wxUsleep
00026 #endif // !wxCHECK_VERSION(2, 6, 0)
00027 
00028 // ----------------------------------------------------------------------------
00029 // wxLuaDebuggerEvent
00030 // ----------------------------------------------------------------------------
00031 
00032 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_CONNECTED)
00033 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_DISCONNECTED)
00034 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_BREAK)
00035 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_PRINT)
00036 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_ERROR)
00037 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_EXIT)
00038 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_STACK_ENUM)
00039 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_STACK_ENTRY_ENUM)
00040 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_TABLE_ENUM)
00041 DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_EVALUATE_EXPR)
00042 //DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_STARTDEBUGGER)
00043 //DEFINE_EVENT_TYPE(wxEVT_WXLUA_DEBUGGER_STOPDEBUGGER)
00044 
00045 IMPLEMENT_DYNAMIC_CLASS(wxLuaDebuggerEvent, wxEvent)
00046 
00047 wxLuaDebuggerEvent::wxLuaDebuggerEvent(const wxLuaDebuggerEvent& event)
00048                    :wxEvent(event),
00049                     m_line_number(event.m_line_number),
00050                     m_fileName(event.m_fileName),
00051                     m_strMessage(event.m_strMessage),
00052                     m_has_message(event.m_has_message),
00053                     m_lua_ref(event.m_lua_ref),
00054                     m_debugData(wxNullLuaDebugData),
00055                     m_enabled_flag(event.m_enabled_flag)
00056 {
00057     SetDebugData(event.GetReference(), event.GetDebugData());
00058 }
00059 
00060 wxLuaDebuggerEvent::wxLuaDebuggerEvent(wxEventType eventType,
00061                                        wxObject* eventObject,
00062                                        int line_number,
00063                                        const wxString &file, bool enabled_flag)
00064                    :wxEvent(0, eventType),
00065                     m_line_number(line_number),
00066                     m_fileName(file),
00067                     m_has_message(false),
00068                     m_lua_ref(-1),
00069                     m_debugData(wxNullLuaDebugData),
00070                     m_enabled_flag(enabled_flag)
00071 {
00072     SetEventObject(eventObject);
00073 }
00074 
00075 void wxLuaDebuggerEvent::SetMessage(const wxString& message)
00076 {
00077     m_strMessage  = message;
00078     m_has_message = true;
00079 }
00080 
00081 void wxLuaDebuggerEvent::SetDebugData(long nReference, const wxLuaDebugData& debugData)
00082 {
00083     m_lua_ref   = nReference;
00084     m_debugData = debugData;
00085 }
00086 
00087 // ----------------------------------------------------------------------------
00088 // wxLuaDebuggerStackDialog
00089 // ----------------------------------------------------------------------------
00090 IMPLEMENT_ABSTRACT_CLASS(wxLuaDebuggerStackDialog, wxLuaStackDialog)
00091 
00092 wxLuaDebuggerStackDialog::wxLuaDebuggerStackDialog(wxLuaDebuggerBase* luaDebugger,
00093                                                    wxWindow* parent, wxWindowID id,
00094                                                    const wxString& title,
00095                                                    const wxPoint& pos, const wxSize& size)
00096                          : m_luaDebugger(luaDebugger)
00097 {
00098     wxCHECK_RET(m_luaDebugger != NULL, wxT("Invalid wxLuaDebuggerBase in wxLuaDebuggerStackDialog"));
00099     // use delayed creation to allow our virtual functions to work
00100     Create(wxNullLuaState, parent, id, title, pos, size);
00101 }
00102 
00103 wxLuaDebuggerStackDialog::~wxLuaDebuggerStackDialog()
00104 {
00105     if (m_luaDebugger != NULL)
00106         m_luaDebugger->ClearDebugReferences();
00107 }
00108 
00109 void wxLuaDebuggerStackDialog::EnumerateStack()
00110 {
00111     wxCHECK_RET(m_luaDebugger, wxT("Invalid wxLuaDebuggerServer"));
00112     wxBeginBusyCursor(); // ended in wxLuaDebuggerBase::OnDebugXXX
00113     m_luaDebugger->EnumerateStack();
00114 }
00115 
00116 void wxLuaDebuggerStackDialog::EnumerateStackEntry(int nEntry)
00117 {
00118     wxCHECK_RET(m_luaDebugger, wxT("Invalid wxLuaDebuggerServer"));
00119     wxBeginBusyCursor(); // ended in wxLuaDebuggerBase::OnDebugXXX
00120     m_luaDebugger->EnumerateStackEntry(nEntry);
00121 }
00122 
00123 void wxLuaDebuggerStackDialog::EnumerateTable(int nRef, int nEntry, long lc_item)
00124 {
00125     wxCHECK_RET(m_luaDebugger, wxT("Invalid wxLuaDebuggerServer"));
00126     wxBeginBusyCursor(); // ended in wxLuaDebuggerBase::OnDebugXXX
00127     m_luaDebugger->EnumerateTable(nRef, nEntry, lc_item);
00128 }
00129 
00130 void wxLuaDebuggerStackDialog::EnumerateGlobalData(long lc_item)
00131 {
00132     wxCHECK_RET(m_luaDebugger, wxT("Invalid wxLuaDebuggerServer"));
00133     wxBeginBusyCursor(); // ended in wxLuaDebuggerBase::OnDebugXXX
00134     m_luaDebugger->EnumerateTable(-1, -1, lc_item);
00135 }
00136 
00137 // ----------------------------------------------------------------------------
00138 // wxLuaDebuggerProcess
00139 // ----------------------------------------------------------------------------
00140 
00141 void wxLuaDebuggerProcess::OnTerminate(int pid, int status)
00142 {
00143     // If this is being deleted from the destructor of wxLuaDebuggerBase
00144     //   it has already been NULLed so don't send event.
00145     if (m_debugger && m_debugger->m_debuggeeProcess)
00146     {
00147         // we don't use the event handler, but this is good enough.
00148         wxProcessEvent event(m_id, pid, status);
00149         m_debugger->OnEndDebugeeProcess(event);
00150 
00151         m_debugger->m_debuggeeProcess = NULL;
00152         m_debugger->m_debuggeeProcessID = -1;
00153     }
00154 
00155     delete this;
00156 }
00157 
00158 // ----------------------------------------------------------------------------
00159 // wxLuaDebuggerBase
00160 // ----------------------------------------------------------------------------
00161 
00162 IMPLEMENT_ABSTRACT_CLASS(wxLuaDebuggerBase, wxEvtHandler)
00163 
00164 wxString wxLuaDebuggerBase::sm_programName;
00165 wxString wxLuaDebuggerBase::sm_networkName;
00166 
00167 BEGIN_EVENT_TABLE(wxLuaDebuggerBase, wxEvtHandler)
00168     EVT_WXLUA_DEBUGGER_STACK_ENUM(       wxID_ANY, wxLuaDebuggerBase::OnDebugStackEnum)
00169     EVT_WXLUA_DEBUGGER_STACK_ENTRY_ENUM( wxID_ANY, wxLuaDebuggerBase::OnDebugStackEntryEnum)
00170     EVT_WXLUA_DEBUGGER_TABLE_ENUM(       wxID_ANY, wxLuaDebuggerBase::OnDebugTableEnum)
00171 
00172     //EVT_END_PROCESS(ID_WXLUASOCKET_DEBUGGEE_PROCESS, wxLuaDebuggerBase::OnEndDebugeeProcess)
00173 END_EVENT_TABLE()
00174 
00175 wxLuaDebuggerBase::wxLuaDebuggerBase(int port_number)
00176                   :wxEvtHandler(), m_port_number(port_number),
00177                    m_stackDialog(NULL),
00178                    m_debuggeeProcess(NULL), m_debuggeeProcessID(-1)
00179 {
00180     // Initialize the debuggee program name if not already set
00181     if (sm_programName.IsEmpty())
00182         sm_programName = wxTheApp->argv[0];
00183 
00184     // Initialize the debuggee network name if not already set
00185     if (sm_networkName.IsEmpty())
00186     {
00187 #ifdef __WXMSW__
00188         sm_networkName = wxGetHostName();
00189 #else
00190         sm_networkName = wxT("localhost");
00191 #endif // __WXMSW__
00192     }
00193 }
00194 
00195 wxLuaDebuggerBase::~wxLuaDebuggerBase()
00196 {
00197     //wxPrintf(wxT("~wxLuaDebuggerBase the m_debuggeeProcess %p %d exists %d\n"), m_debuggeeProcess, m_debuggeeProcessID, wxProcess::Exists(m_debuggeeProcessID)); fflush(stdout);
00198 
00199     // we don't delete the the process, we kill it and its OnTerminate deletes it
00200     if ((m_debuggeeProcess != NULL) && (m_debuggeeProcessID > 0) &&
00201          wxProcess::Exists(m_debuggeeProcessID))
00202     {
00203         m_debuggeeProcess->m_debugger = NULL;
00204         m_debuggeeProcess = NULL;
00205         wxProcess::Kill(m_debuggeeProcessID, wxSIGKILL, wxKILL_CHILDREN);
00206     }
00207 }
00208 
00209 long wxLuaDebuggerBase::StartClient()
00210 {
00211     if (m_debuggeeProcess == NULL)
00212     {
00213         m_debuggeeProcess = new wxLuaDebuggerProcess(this, ID_WXLUASOCKET_DEBUGGEE_PROCESS);
00214         wxString command = wxString::Format(wxT("%s -d%s:%u"),
00215                                             GetProgramName().c_str(),
00216                                             GetNetworkName().c_str(),
00217                                             m_port_number);
00218 
00219         m_debuggeeProcessID = wxExecute(command, wxEXEC_ASYNC|wxEXEC_MAKE_GROUP_LEADER, m_debuggeeProcess);
00220 
00221         if (m_debuggeeProcessID < 1)
00222             KillDebuggee();
00223     }
00224 
00225     return m_debuggeeProcessID;
00226 }
00227 
00228 bool wxLuaDebuggerBase::AddBreakPoint(const wxString &fileName, int lineNumber)
00229 {
00230     return CheckSocketConnected(true, wxT("Debugger AddBreakPoint")) && CheckSocketWrite(
00231            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_ADD_BREAKPOINT) &&
00232            GetSocketBase()->WriteString(fileName) &&
00233            GetSocketBase()->WriteInt32(lineNumber),
00234            wxT("Debugger AddBreakPoint"));
00235 }
00236 
00237 bool wxLuaDebuggerBase::RemoveBreakPoint(const wxString &fileName, int lineNumber)
00238 {
00239     return CheckSocketConnected(true, wxT("Debugger RemoveBreakPoint")) && CheckSocketWrite(
00240            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_REMOVE_BREAKPOINT) &&
00241            GetSocketBase()->WriteString(fileName) &&
00242            GetSocketBase()->WriteInt32(lineNumber),
00243            wxT("Debugger RemoveBreakPoint"));
00244 }
00245 
00246 bool wxLuaDebuggerBase::DisableBreakPoint(const wxString &fileName, int lineNumber)
00247 {
00248     return CheckSocketConnected(true, wxT("Debugger DisableBreakPoint")) && CheckSocketWrite(
00249            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DISABLE_BREAKPOINT) &&
00250            GetSocketBase()->WriteString(fileName) &&
00251            GetSocketBase()->WriteInt32(lineNumber),
00252            wxT("Debugger DisableBreakPoint"));
00253 }
00254 
00255 bool wxLuaDebuggerBase::EnableBreakPoint(const wxString &fileName, int lineNumber)
00256 {
00257     return CheckSocketConnected(true, wxT("Debugger EnableBreakPoint")) && CheckSocketWrite(
00258            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_ENABLE_BREAKPOINT) &&
00259            GetSocketBase()->WriteString(fileName) &&
00260            GetSocketBase()->WriteInt32(lineNumber),
00261            wxT("Debugger EnableBreakPoint"));
00262 }
00263 
00264 bool wxLuaDebuggerBase::ClearAllBreakPoints()
00265 {
00266     return CheckSocketConnected(true, wxT("Debugger ClearAllBreakPoints")) && CheckSocketWrite(
00267            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_CLEAR_ALL_BREAKPOINTS),
00268            wxT("Debugger ClearAllBreakPoints"));
00269 }
00270 
00271 bool wxLuaDebuggerBase::Run(const wxString &fileName, const wxString &buffer)
00272 {
00273     return CheckSocketConnected(true, wxT("Debugger Run")) && CheckSocketWrite(
00274            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_RUN_BUFFER) &&
00275            GetSocketBase()->WriteString(fileName) &&
00276            GetSocketBase()->WriteString(buffer),
00277            wxT("Debugger Run"));
00278 }
00279 
00280 bool wxLuaDebuggerBase::Step()
00281 {
00282     return CheckSocketConnected(true, wxT("Debugger Step")) && CheckSocketWrite(
00283            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEP),
00284            wxT("Debugger Step"));
00285 }
00286 
00287 bool wxLuaDebuggerBase::StepOver()
00288 {
00289     return CheckSocketConnected(true, wxT("Debugger StepOver")) && CheckSocketWrite(
00290            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEPOVER),
00291            wxT("Debugger StepOver"));
00292 }
00293 
00294 bool wxLuaDebuggerBase::StepOut()
00295 {
00296     return CheckSocketConnected(true, wxT("Debugger StepOut")) && CheckSocketWrite(
00297            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DEBUG_STEPOUT),
00298            wxT("Debugger StepOut"));
00299 }
00300 
00301 bool wxLuaDebuggerBase::Continue()
00302 {
00303     return CheckSocketConnected(true, wxT("Debugger Continue")) && CheckSocketWrite(
00304            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DEBUG_CONTINUE),
00305            wxT("Debugger Continue"));
00306 }
00307 
00308 bool wxLuaDebuggerBase::Break()
00309 {
00310     return CheckSocketConnected(true, wxT("Debugger Break")) && CheckSocketWrite(
00311            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_DEBUG_BREAK),
00312            wxT("Debugger Break"));
00313 }
00314 
00315 bool wxLuaDebuggerBase::Reset()
00316 {
00317     return CheckSocketConnected(true, wxT("Debugger Reset")) && CheckSocketWrite(
00318            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_RESET),
00319            wxT("Debugger Reset"));
00320 }
00321 
00322 bool wxLuaDebuggerBase::EnumerateStack()
00323 {
00324     return CheckSocketConnected(true, wxT("Debugger EnumerateStack")) && CheckSocketWrite(
00325            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_STACK),
00326            wxT("Debugger EnumerateStack"));
00327 }
00328 
00329 bool wxLuaDebuggerBase::EnumerateStackEntry(int stackEntry)
00330 {
00331     return CheckSocketConnected(true, wxT("Debugger EnumerateStackEntry")) && CheckSocketWrite(
00332            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_STACK_ENTRY) &&
00333            GetSocketBase()->WriteInt32(stackEntry),
00334            wxT("Debugger EnumerateStackEntry"));
00335 }
00336 
00337 bool wxLuaDebuggerBase::EnumerateTable(int tableRef, int nIndex, long nItemNode)
00338 {
00339     return CheckSocketConnected(true, wxT("Debugger EnumerateTable")) && CheckSocketWrite(
00340            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_ENUMERATE_TABLE_REF) &&
00341            GetSocketBase()->WriteInt32(tableRef) &&
00342            GetSocketBase()->WriteInt32(nIndex) &&
00343            GetSocketBase()->WriteLong(nItemNode),
00344            wxT("Debugger EnumerateTable"));
00345 }
00346 
00347 bool wxLuaDebuggerBase::ClearDebugReferences()
00348 {
00349     return CheckSocketConnected(true, wxT("Debugger ClearDebugReferences")) && CheckSocketWrite(
00350            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_CLEAR_DEBUG_REFERENCES),
00351            wxT("Debugger ClearDebugReferences"));
00352 }
00353 
00354 bool wxLuaDebuggerBase::EvaluateExpr(int exprRef, const wxString &strExpression)
00355 {
00356     return CheckSocketConnected(true, wxT("Debugger EvaluateExpr")) && CheckSocketWrite(
00357            GetSocketBase()->WriteCmd(wxLUASOCKET_DEBUGGER_CMD_EVALUATE_EXPR) &&
00358            GetSocketBase()->WriteInt32(exprRef) &&
00359            GetSocketBase()->WriteString(strExpression),
00360            wxT("Debugger EvaluateExpr"));
00361 }
00362 
00363 //extern wxString wxLuaSocketCmdEventMsg(int val);
00364 
00365 // This function shouldn't modify any internal variables without using a
00366 // critical section since the wxLuaDebuggerCServer calls it from the thread.
00367 int wxLuaDebuggerBase::HandleDebuggeeEvent(int event_type)
00368 {
00369     wxCHECK_MSG(GetSocketBase(), event_type, wxT("Invalid socket"));
00370 
00371     //wxLuaDebuggerEvent d(wxEVT_WXLUA_DEBUGGER_PRINT, this);
00372     //d.SetMessage(wxT("wxLuaDebugger : ") + wxLuaSocketCmdEventMsg(event_type));
00373     //SendEvent(d);
00374 
00375     switch (event_type)
00376     {
00377         case wxLUASOCKET_DEBUGGEE_EVENT_BREAK:
00378         {
00379             wxString fileName;
00380             wxInt32  lineNumber = 0;
00381 
00382             if (CheckSocketRead(
00383                 GetSocketBase()->ReadString(fileName) &&
00384                 GetSocketBase()->ReadInt32(lineNumber),
00385                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_BREAK")))
00386             {
00387                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_BREAK, this, lineNumber, fileName);
00388                 SendEvent(debugEvent);
00389             }
00390             else return -1;
00391 
00392             break;
00393         }
00394         case wxLUASOCKET_DEBUGGEE_EVENT_PRINT:
00395         {
00396             wxString strMessage;
00397 
00398             if (CheckSocketRead(
00399                 GetSocketBase()->ReadString(strMessage),
00400                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_PRINT")))
00401             {
00402                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_PRINT, this);
00403                 debugEvent.SetMessage(strMessage);
00404                 SendEvent(debugEvent);
00405             }
00406             else return -1;
00407 
00408             break;
00409         }
00410         case wxLUASOCKET_DEBUGGEE_EVENT_ERROR:
00411         {
00412             wxString strMessage;
00413 
00414             if (CheckSocketRead(
00415                 GetSocketBase()->ReadString(strMessage),
00416                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_ERROR")))
00417             {
00418                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_ERROR, this);
00419                 debugEvent.SetMessage(strMessage);
00420                 SendEvent(debugEvent);
00421             }
00422             else return -1;
00423 
00424             break;
00425         }
00426         case wxLUASOCKET_DEBUGGEE_EVENT_EXIT:
00427         {
00428             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_EXIT, this);
00429             wxPostEvent(this, debugEvent);
00430             break;
00431         }
00432         case wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENUM:
00433         {
00434             wxLuaDebugData debugData(true);
00435 
00436             if (CheckSocketRead(
00437                 GetSocketBase()->ReadDebugData(debugData),
00438                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENUM")))
00439             {
00440                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_STACK_ENUM, this);
00441                 debugEvent.SetDebugData(-1, debugData);
00442                 SendEvent(debugEvent);
00443             }
00444             else return -1;
00445 
00446             break;
00447         }
00448         case wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENTRY_ENUM:
00449         {
00450             wxInt32 stackRef = 0;
00451             wxLuaDebugData debugData(true);
00452 
00453             if (CheckSocketRead(
00454                 GetSocketBase()->ReadInt32(stackRef) &&
00455                 GetSocketBase()->ReadDebugData(debugData),
00456                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_STACK_ENTRY_ENUM")))
00457             {
00458                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_STACK_ENTRY_ENUM, this);
00459                 debugEvent.SetDebugData(stackRef, debugData);
00460                 SendEvent(debugEvent);
00461             }
00462             else return -1;
00463 
00464             break;
00465         }
00466         case wxLUASOCKET_DEBUGGEE_EVENT_TABLE_ENUM:
00467         {
00468             long itemNode = 0;
00469             wxLuaDebugData debugData(true);
00470 
00471             if (CheckSocketRead(
00472                 GetSocketBase()->ReadLong(itemNode) &&
00473                 GetSocketBase()->ReadDebugData(debugData),
00474                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_TABLE_ENUM")))
00475             {
00476                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_TABLE_ENUM, this);
00477                 debugEvent.SetDebugData(itemNode, debugData);
00478                 SendEvent(debugEvent);
00479             }
00480             else return -1;
00481 
00482             break;
00483         }
00484         case wxLUASOCKET_DEBUGGEE_EVENT_EVALUATE_EXPR:
00485         {
00486             wxInt32 exprRef = 0;
00487             wxString strResult;
00488 
00489             if (CheckSocketRead(
00490                 GetSocketBase()->ReadInt32(exprRef) &&
00491                 GetSocketBase()->ReadString(strResult),
00492                 wxT("Debugger wxLUASOCKET_DEBUGGEE_EVENT_EVALUATE_EXPR")))
00493             {
00494                 wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_EVALUATE_EXPR, this);
00495                 debugEvent.SetMessage(strResult);
00496                 debugEvent.SetDebugData(exprRef);
00497                 SendEvent(debugEvent);
00498             }
00499             else return -1;
00500 
00501             break;
00502         }
00503         default : return -1; // don't know this event?
00504     }
00505 
00506     return event_type;
00507 }
00508 
00509 
00510 bool wxLuaDebuggerBase::CheckSocketConnected(bool send_event, const wxString& msg)
00511 {
00512     if (GetSocketBase() == NULL)
00513     {
00514         if (send_event)
00515         {
00516             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_DISCONNECTED, this);
00517             debugEvent.SetMessage(wxT("Debugger socket not created. ") + msg);
00518             SendEvent(debugEvent);
00519         }
00520 
00521         return false;
00522     }
00523     else if (!GetSocketBase()->IsConnected())
00524     {
00525         if (send_event)
00526         {
00527             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_DISCONNECTED, this);
00528             debugEvent.SetMessage(wxT("Debugger socket not connected. ") + msg);
00529             SendEvent(debugEvent);
00530         }
00531 
00532         return false;
00533     }
00534 
00535     return true;
00536 }
00537 bool wxLuaDebuggerBase::CheckSocketRead(bool read_ok, const wxString& msg)
00538 {
00539     if (!read_ok)
00540     {
00541         wxString s = wxT("Failed reading from the debugger socket. ") + msg + wxT("\n");
00542         s += GetSocketErrorMsg();
00543 
00544         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_DISCONNECTED, this);
00545         debugEvent.SetMessage(s);
00546         SendEvent(debugEvent);
00547     }
00548 
00549     return read_ok;
00550 }
00551 bool wxLuaDebuggerBase::CheckSocketWrite(bool write_ok, const wxString& msg)
00552 {
00553     if (!write_ok)
00554     {
00555         wxString s = wxT("Failed writing to the debugger socket. ") + msg + wxT("\n");
00556         s += GetSocketErrorMsg();
00557 
00558         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_DISCONNECTED, this);
00559         debugEvent.SetMessage(s);
00560         SendEvent(debugEvent);
00561     }
00562 
00563     return write_ok;
00564 }
00565 
00566 bool wxLuaDebuggerBase::DisplayStackDialog(wxWindow *parent, wxWindowID winid)
00567 {
00568     wxCHECK_MSG(m_stackDialog == NULL, false, wxT("Stack dialog already shown"));
00569 
00570     m_stackDialog = new wxLuaDebuggerStackDialog(this, parent, winid);
00571     m_stackDialog->ShowModal();
00572     m_stackDialog->Destroy();
00573     m_stackDialog = NULL;
00574     return true;
00575 }
00576 
00577 void wxLuaDebuggerBase::OnDebugStackEnum(wxLuaDebuggerEvent &event)
00578 {
00579     if (GetStackDialog() != NULL)
00580         GetStackDialog()->FillStackCombobox(event.GetDebugData());
00581     else
00582         event.Skip();
00583 
00584     wxEndBusyCursor();
00585 }
00586 void wxLuaDebuggerBase::OnDebugStackEntryEnum(wxLuaDebuggerEvent &event)
00587 {
00588     if (GetStackDialog() != NULL)
00589         GetStackDialog()->FillStackEntry(event.GetReference(), event.GetDebugData());
00590     else
00591         event.Skip();
00592 
00593     wxEndBusyCursor();
00594 }
00595 void wxLuaDebuggerBase::OnDebugTableEnum(wxLuaDebuggerEvent &event)
00596 {
00597     if (GetStackDialog() != NULL)
00598         GetStackDialog()->FillTableEntry(event.GetReference(), event.GetDebugData());
00599     else
00600         event.Skip();
00601 
00602     wxEndBusyCursor();
00603 }
00604 
00605 void wxLuaDebuggerBase::OnEndDebugeeProcess(wxProcessEvent& event)
00606 {
00607     //wxPrintf(wxT("OnEndDebugeeProcess the m_debuggeeProcess %p %d exists %d\n"), m_debuggeeProcess, m_debuggeeProcessID, wxProcess::Exists(m_debuggeeProcessID)); fflush(stdout);
00608 
00609     // The process's OnTerminate will null m_debuggeeProcess,
00610     // but if in destructor it's already NULL and don't send event.
00611     if (m_debuggeeProcess != NULL)
00612     {
00613         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_EXIT, this);
00614         debugEvent.SetMessage(wxString::Format(wxT("Process (%d) ended with exit code : %d"), event.GetPid(), event.GetExitCode()));
00615         wxPostEvent(this, debugEvent);
00616     }
00617 
00618     event.Skip();
00619 }
00620 
00621 bool wxLuaDebuggerBase::KillDebuggee()
00622 {
00623     //wxPrintf(wxT("KillDebuggee the m_debuggeeProcess %p %d exists %d\n"), m_debuggeeProcess, m_debuggeeProcessID, wxProcess::Exists(m_debuggeeProcessID)); fflush(stdout);
00624 
00625     if ((m_debuggeeProcess != NULL) && (m_debuggeeProcessID > 0))
00626     {
00627         m_debuggeeProcess->m_debugger = NULL;
00628         m_debuggeeProcess = NULL;
00629 
00630         //if (p->Exists(m_debuggeeProcessID)) should exist since OnTerminate hasn't been called
00631             wxProcess::Kill(m_debuggeeProcessID, wxSIGKILL, wxKILL_CHILDREN);
00632     }
00633     else if (m_debuggeeProcess != NULL) // error starting process?
00634     {
00635         wxLuaDebuggerProcess* p = m_debuggeeProcess;
00636         m_debuggeeProcess->m_debugger = NULL;
00637         m_debuggeeProcess = NULL;
00638         delete p;
00639     }
00640 
00641     m_debuggeeProcessID = -1;
00642 
00643     return true;
00644 }
00645 
00646 #ifdef WXLUASOCKET_USE_C_SOCKET
00647 
00648 // ----------------------------------------------------------------------------
00649 // wxLuaDebuggerCServer::LuaThread
00650 // ----------------------------------------------------------------------------
00651 
00652 void *wxLuaDebuggerCServer::LuaThread::Entry()
00653 {
00654     m_pServer->ThreadFunction();
00655     return 0;
00656 }
00657 
00658 void wxLuaDebuggerCServer::LuaThread::OnExit()
00659 {
00660     wxThread::OnExit();
00661     //m_pServer->m_pThread = NULL;
00662 }
00663 
00664 // ----------------------------------------------------------------------------
00665 // wxLuaDebuggerCServer
00666 // ----------------------------------------------------------------------------
00667 IMPLEMENT_ABSTRACT_CLASS(wxLuaDebuggerCServer, wxLuaDebuggerBase)
00668 
00669 wxLuaDebuggerCServer::wxLuaDebuggerCServer(int port_number)
00670                      :wxLuaDebuggerBase(port_number),
00671                       m_serverSocket(NULL), m_acceptedSocket(NULL),
00672                       m_pThread(NULL),
00673                       m_shutdown(false)
00674 {
00675 }
00676 
00677 wxLuaDebuggerCServer::~wxLuaDebuggerCServer()
00678 {
00679     StopServer();
00680 }
00681 
00682 bool wxLuaDebuggerCServer::StartServer()
00683 {
00684     wxCHECK_MSG(m_serverSocket == NULL, false, wxT("Debugger server socket already created"));
00685 
00686     m_shutdown = false;
00687     m_serverSocket = new wxLuaCSocket();
00688     m_serverSocket->m_name = wxString::Format(wxT("wxLuaDebuggerCServer::m_serverSocket (%ld)"), (long)wxGetProcessId());
00689 
00690     if (m_serverSocket->Listen(m_port_number))
00691     {
00692         wxCHECK_MSG(m_pThread == NULL, false, wxT("Debugger server thread already created"));
00693 
00694         if (!m_shutdown)
00695         {
00696             m_pThread = new wxLuaDebuggerCServer::LuaThread(this);
00697 
00698             return ((m_pThread != NULL) &&
00699                     (m_pThread->Create() == wxTHREAD_NO_ERROR) &&
00700                     (m_pThread->Run()    == wxTHREAD_NO_ERROR));
00701         }
00702     }
00703     else
00704     {
00705         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_ERROR, this);
00706         debugEvent.SetMessage(m_serverSocket->GetErrorMsg(true));
00707         AddPendingEvent(debugEvent);
00708 
00709         delete m_serverSocket;
00710         m_serverSocket = NULL;
00711         m_shutdown = true;
00712     }
00713 
00714     return false;
00715 }
00716 
00717 long wxLuaDebuggerCServer::StartClient()
00718 {
00719     wxCHECK_MSG(m_serverSocket, false, wxT("Debugger server not started"));
00720     wxCHECK_MSG(m_pThread, false, wxT("Debugger server thread not running"));
00721 
00722     if (!m_shutdown)
00723         return wxLuaDebuggerBase::StartClient();
00724 
00725     return m_debuggeeProcessID;
00726 }
00727 
00728 bool wxLuaDebuggerCServer::StopServer()
00729 {
00730     // NO checks, can always call stop server
00731 
00732     // Set the shutdown flag
00733     m_shutdown = true;
00734 
00735     // try to nicely stop the socket if it exists
00736     if (m_acceptedSocket)
00737     {
00738         Reset();
00739         wxMilliSleep(500);
00740     }
00741 
00742     // close the session socket, but first NULL it so we won't try to use it
00743     //m_acceptSockCritSect.Enter();
00744     wxLuaSocket *acceptedSocket = m_acceptedSocket;
00745     //m_acceptedSocket = NULL;
00746     //m_acceptSockCritSect.Leave();
00747 
00748     if (acceptedSocket != NULL)
00749     {
00750         if (!acceptedSocket->Shutdown(SD_BOTH))
00751         {
00752             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_ERROR, this);
00753             debugEvent.SetMessage(acceptedSocket->GetErrorMsg(true));
00754             AddPendingEvent(debugEvent);
00755         }
00756 
00757         wxMilliSleep(500);
00758         //m_acceptedSocket = NULL;
00759         //delete acceptedSocket;
00760     }
00761 
00762     // close the server socket, if accepted socket created it will already
00763     // have been deleted
00764     if (m_serverSocket != NULL)
00765     {
00766         wxLuaSocket *serverSocket = m_serverSocket;
00767         m_serverSocket = NULL;
00768 
00769         // close the server socket by connecting to the socket, thus
00770         // completing the 'accept'. If a client has not connected, this
00771         // code will satisfy the accept the m_shutdown flag will be set
00772         // so the thread will not loop and instead will just destroy the
00773         // session socket object and return.
00774         wxLuaSocket closeSocket;
00775         closeSocket.m_name = wxString::Format(wxT("wxLuaDebuggerCServer closeSocket (%ld)"), (long)wxGetProcessId());
00776 
00777         if (!closeSocket.Connect(GetNetworkName(),  m_port_number) ||
00778             !closeSocket.Shutdown(SD_BOTH))
00779         {
00780             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_ERROR, this);
00781             debugEvent.SetMessage(serverSocket->GetErrorMsg(true));
00782             AddPendingEvent(debugEvent);
00783         }
00784 
00785         wxMilliSleep(100);
00786 
00787         delete serverSocket;
00788     }
00789 
00790     // One of the above two operations terminates the thread. Wait for it to stop.
00791     if ((m_pThread != NULL) && m_pThread->IsRunning())
00792         m_pThread->Wait();
00793 
00794     delete m_pThread;
00795     m_pThread = NULL;
00796 
00797     return true;
00798 }
00799 
00800 void wxLuaDebuggerCServer::ThreadFunction()
00801 {
00802     wxCHECK_RET(m_serverSocket, wxT("Invalid server socket"));
00803     wxCHECK_RET(m_acceptedSocket == NULL, wxT("The debugger server has already accepted a socket connection"));
00804 
00805     m_acceptedSocket = m_serverSocket->Accept();
00806     if (!m_acceptedSocket)
00807     {
00808         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_ERROR, this);
00809         debugEvent.SetMessage(m_serverSocket->GetErrorMsg(true));
00810         AddPendingEvent(debugEvent);
00811     }
00812     else
00813     {
00814         m_acceptedSocket->m_name = wxString::Format(wxT("wxLuaDebuggerCServer::m_acceptedSocket (%ld)"), (long)wxGetProcessId());
00815 
00816         wxLuaSocket *serverSocket = m_serverSocket;
00817         m_serverSocket = NULL;
00818         delete serverSocket;
00819 
00820         wxThread::Sleep(500);  // why ??
00821 
00822         // Notify that a client has connected and we are ready to debug
00823         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_CONNECTED, this);
00824         AddPendingEvent(debugEvent);
00825 
00826         unsigned char debug_event = 0; // wxLuaSocketDebuggeeEvents_Type
00827 
00828         // Enter the debug loop
00829         while (!m_pThread->TestDestroy() && !m_shutdown && m_acceptedSocket)
00830         {
00831             debug_event = wxLUASOCKET_DEBUGGEE_EVENT_EXIT;
00832 
00833             {
00834                 // lock the critical section while we access it
00835                 wxCriticalSectionLocker locker(m_acceptSockCritSect);
00836                 if (m_shutdown || (m_acceptedSocket == NULL) || !m_acceptedSocket->ReadCmd(debug_event))
00837                 {
00838                     m_shutdown = true;
00839                     break;
00840                 }
00841             }
00842 
00843             if((debug_event == wxLUASOCKET_DEBUGGEE_EVENT_EXIT) ||
00844                (HandleDebuggeeEvent(debug_event) != -1))
00845             {
00846                 // don't send exit event until we've closed the socket
00847                 if (debug_event == wxLUASOCKET_DEBUGGEE_EVENT_EXIT)
00848                 {
00849                     m_shutdown = true;
00850                     break;
00851                 }
00852             }
00853         }
00854 
00855         wxCriticalSectionLocker locker(m_acceptSockCritSect);
00856         // delete the accepted socket
00857         if (m_acceptedSocket != NULL)
00858         {
00859             wxLuaSocket *acceptedSocket = m_acceptedSocket;
00860             m_acceptedSocket = NULL;
00861             delete acceptedSocket;
00862         }
00863     }
00864 
00865     // Send the exit event, now that everything is shut down
00866     //if (debug_event == wxLUASOCKET_DEBUGGEE_EVENT_EXIT)
00867     {
00868         wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_EXIT, this);
00869         wxPostEvent(this, debugEvent);
00870     }
00871 }
00872 
00873 wxString wxLuaDebuggerCServer::GetSocketErrorMsg()
00874 {
00875     wxString s;
00876 
00877     if (m_serverSocket)
00878         s += m_serverSocket->GetErrorMsg(true);
00879     if (m_acceptedSocket)
00880         s += m_acceptedSocket->GetErrorMsg(true);
00881 
00882     return s;
00883 }
00884 
00885 #else // !WXLUASOCKET_USE_C_SOCKET
00886 
00887 // ---------------------------------------------------------------------------
00888 // wxLuaDebuggerwxSocketServer
00889 // ---------------------------------------------------------------------------
00890 IMPLEMENT_ABSTRACT_CLASS(wxLuaDebuggerwxSocketServer, wxLuaDebuggerBase)
00891 
00892 BEGIN_EVENT_TABLE(wxLuaDebuggerwxSocketServer, wxLuaDebuggerBase)
00893   EVT_SOCKET(ID_WXLUA_SERVER,  wxLuaDebuggerwxSocketServer::OnServerEvent)
00894   EVT_SOCKET(ID_WXLUA_SOCKET,  wxLuaDebuggerwxSocketServer::OnSocketEvent)
00895 END_EVENT_TABLE()
00896 
00897 
00898 wxLuaDebuggerwxSocketServer::wxLuaDebuggerwxSocketServer(int port_number)
00899                             :wxLuaDebuggerBase(port_number),
00900                              m_serverSocket(NULL), m_acceptedSocket(NULL)
00901 {
00902 }
00903 
00904 wxLuaDebuggerwxSocketServer::~wxLuaDebuggerwxSocketServer()
00905 {
00906     StopServer();
00907 }
00908 
00909 // Start Debugging Service
00910 bool wxLuaDebuggerwxSocketServer::StartServer()
00911 {
00912     if (!m_serverSocket)
00913     {
00914         // Create the address - defaults to localhost:0 initially
00915         wxIPV4address addr;
00916         addr.Service(m_port_number);
00917 
00918         // Create the server socket
00919         m_serverSocket = new wxSocketServer(addr, wxSOCKET_NOWAIT|wxSOCKET_BLOCK);
00920         m_serverSocket->SetEventHandler(*this, ID_WXLUA_SERVER);
00921         m_serverSocket->SetNotify(wxSOCKET_CONNECTION_FLAG);
00922         m_serverSocket->SetFlags(wxSOCKET_BLOCK);
00923         m_serverSocket->Notify(true);
00924     }
00925 
00926     return m_serverSocket->Ok();
00927 }
00928 
00929 bool wxLuaDebuggerwxSocketServer::StopServer()
00930 {
00931     if (m_acceptedSocket)
00932     {
00933         m_acceptedSocket->GetSocket()->Notify(false);
00934         m_acceptedSocket->Destroy();
00935         delete m_acceptedSocket;
00936         m_acceptedSocket = NULL;
00937     }
00938 
00939     if (m_serverSocket)
00940     {
00941         m_serverSocket->Notify(false);
00942         m_serverSocket->Destroy(); // this deletes it too
00943         m_serverSocket = NULL;
00944     }
00945 
00946     return true;
00947 }
00948 
00949 long wxLuaDebuggerwxSocketServer::StartClient()
00950 {
00951     return wxLuaDebuggerBase::StartClient();
00952 }
00953 
00954 wxString wxLuaDebuggerwxSocketServer::GetSocketErrorMsg()
00955 {
00956     wxString s;
00957     if (m_acceptedSocket)
00958         s += m_acceptedSocket->GetErrorMsg(true);
00959 
00960     return s;
00961 }
00962 
00963 void wxLuaDebuggerwxSocketServer::OnServerEvent(wxSocketEvent& event)
00964 {
00965     switch(event.GetSocketEvent())
00966     {
00967         case wxSOCKET_CONNECTION:
00968         {
00969             wxSocketBase *sock = m_serverSocket->Accept(false);
00970             if (!sock)
00971             {
00972                 // Error
00973                 return;
00974             }
00975 
00976             sock->SetFlags(wxSOCKET_NOWAIT);
00977             m_acceptedSocket = new wxLuawxSocket(sock);
00978             m_acceptedSocket->m_port_number = m_port_number; // can't get it from wxSocketBase
00979             m_acceptedSocket->m_name = wxString::Format(wxT("wxLuaDebuggerwxSocketServer::m_acceptedSocket (%ld)"), (long)wxGetProcessId());
00980 
00981             // Setup Handler
00982             sock->SetEventHandler(*this, ID_WXLUA_SOCKET);
00983             sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
00984             sock->Notify(true);
00985 
00986             wxMilliSleep(500);
00987 
00988             // Notify that a client has connected and we are ready to debug
00989             wxLuaDebuggerEvent debugEvent(wxEVT_WXLUA_DEBUGGER_DEBUGGEE_CONNECTED, this);
00990             AddPendingEvent(debugEvent);
00991 
00992             break;
00993         }
00994 
00995         default:
00996             // Error
00997             break;
00998     }
00999 }
01000 
01001 // Handle Commands from debugger (and lost connections)
01002 void wxLuaDebuggerwxSocketServer::OnSocketEvent(wxSocketEvent& event)
01003 {
01004     wxSocketBase *sock = event.GetSocket();
01005 
01006     // Now we process the event
01007     switch(event.GetSocketEvent())
01008     {
01009         case wxSOCKET_INPUT:
01010         {
01011             // We disable input events, so that the test doesn't trigger
01012             // wxSocketEvent again.
01013             sock->SetNotify(wxSOCKET_LOST_FLAG);
01014 
01015             unsigned char debugEvent = 0; // wxLuaSocketDebuggeeEvents_Type
01016             if (m_acceptedSocket->ReadCmd(debugEvent))
01017                 HandleDebuggeeEvent(debugEvent);
01018 
01019             // Enable input events again.
01020             sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
01021             break;
01022         }
01023         case wxSOCKET_LOST:
01024         {
01025             m_acceptedSocket->Destroy();
01026             delete m_acceptedSocket;
01027             m_acceptedSocket = NULL;
01028             break;
01029         }
01030         default:
01031             // Error
01032             break;
01033     }
01034 }
01035 
01036 #endif // WXLUASOCKET_USE_C_SOCKET
Generated on Tue Jul 13 10:30:39 2010 for wxLua by  doxygen 1.6.3