From 3305c6d980abfee143e46d012a5a74bd6b762909 Mon Sep 17 00:00:00 2001
From: ussrhero <ussrhero@outlook.com>
Date: Wed, 3 Oct 2018 21:56:19 +0300
Subject: [PATCH] added : breakpoint.detach method ( convert strong breakpoint
 reference to  weak )

---
 pykd/pyeventhandler.cpp    | 29 +++++++++++++++++++++++++++++
 pykd/pyeventhandler.h      |  2 ++
 pykd/pymod.cpp             |  2 ++
 test/scripts/breakpoint.py | 11 +++++++++++
 4 files changed, 44 insertions(+)

diff --git a/pykd/pyeventhandler.cpp b/pykd/pyeventhandler.cpp
index 69e1bc1..d4ac289 100644
--- a/pykd/pyeventhandler.cpp
+++ b/pykd/pyeventhandler.cpp
@@ -654,7 +654,36 @@ void Breakpoint::remove()
     {
         m_breakpoint->remove();
         m_breakpoint = 0;
+        return;
     }
+
+    throw kdlib::DbgException("Cannot remove breakpoint, it is detached");
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+Breakpoint* Breakpoint::detach()
+{
+    AutoRestorePyState  pystate;
+
+    if (m_weakBp)
+    {
+        throw kdlib::DbgException("Cannot detach 'weak' breakpoint");
+    }
+
+    if (m_breakpoint)
+    {
+        if (m_callback)
+        {
+            throw kdlib::DbgException("Cannot detach breakpoint with callback");
+        }
+
+        auto  bp = m_breakpoint;
+        m_breakpoint = 0;
+        return new Breakpoint(bp);
+    }
+
+    throw kdlib::DbgException("Cannot remove breakpoint, it is detached");
 }
 
 /////////////////////////////////////////////////////////////////////////////////
diff --git a/pykd/pyeventhandler.h b/pykd/pyeventhandler.h
index c16f452..486571e 100644
--- a/pykd/pyeventhandler.h
+++ b/pykd/pyeventhandler.h
@@ -105,6 +105,8 @@ public:
 
     void remove();
 
+    Breakpoint* detach();
+
 private:
 
     PyThreadState*  m_pystate;
diff --git a/pykd/pymod.cpp b/pykd/pymod.cpp
index 3e830dc..b11dc91 100644
--- a/pykd/pymod.cpp
+++ b/pykd/pymod.cpp
@@ -1391,6 +1391,8 @@ void pykd_init()
             "Remove breakpoint" )
         .def("onHit", &Breakpoint::onHit,
             "Breakpoint hit callback")
+        .def("detach", &Breakpoint::detach, python::return_value_policy<python::manage_new_object>(),
+            "detach breakpoint")
         ;
 
     python::class_<kdlib::SyntheticSymbol>(
diff --git a/test/scripts/breakpoint.py b/test/scripts/breakpoint.py
index 058bd81..795379e 100644
--- a/test/scripts/breakpoint.py
+++ b/test/scripts/breakpoint.py
@@ -184,3 +184,14 @@ class BreakpointTest( unittest.TestCase ):
         bp = pykd.getBp(0)
         self.assertEqual(0x100, bp.getOffset())
 
+    def testDoubleRemove(self):      
+        bp = pykd.setBp( self.targetModule.CdeclFunc )
+        bp.remove()
+        self.assertRaises( pykd.DbgException, bp.remove )
+
+    def testDetach(self):      
+        bp = pykd.setBp( self.targetModule.CdeclFunc ).detach()
+        self.assertEqual(1, pykd.getNumberBreakpoints())
+        self.assertRaises(pykd.DbgException, bp.detach )
+        del bp
+        self.assertEqual(1, pykd.getNumberBreakpoints()) 
\ No newline at end of file