Loading ...
Sorry, an error occurred while loading the content.
 

RE: remote debugging ideas for vimscripts

Expand Messages
  • Michael Geddes
    Hari et al, I think the remote debugging idea is quite kool.. so I ve done a bit of digging. As a start, I suggest that we turn off debug mode and redir_off
    Message 1 of 5 , Jul 1, 2003
      Hari et al,

      I think the remote debugging idea is quite kool.. so I've done a bit of
      digging.

      As a start, I suggest that we turn off debug mode and redir_off at
      the start of the
      message handler for remote_expr() on the server and restore them at the
      end.

      In os_mswin.c.. this is done by adding the + lines in the code block
      below. This fixed problem number 1.. which is that the call doesn't
      return until you type 'cont' on the server. I've also checked that you
      can still :breakadd the function that is being called to allow debugging
      of remote calls.

      The second problem I haven't got much info on.. or time to do it.
      However running the debug version under msdev debugger, I'm seeing:

      HEAP[gvimd.exe]: HEAP: Free Heap block c41610 modified at c41638
      after it was freed

      on the server when you type

      :call remote_send('GVIMD', ":let @z=GetVimCmdOutput('ls')\<CR>")

      on the client vim... which isn't very promising. If I do get time I'll
      investigate!

      //.





      //.
      ----------8<---------------

      static LRESULT CALLBACK
      Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
      {
      if (msg == WM_COPYDATA)
      {
      /* This is a message from another Vim. The dwData member of the
      * COPYDATASTRUCT determines the type of message:
      * COPYDATA_KEYS:
      * A key sequence. We are a server, and a client wants
      these keys
      * adding to the input queue.
      * COPYDATA_REPLY:
      * A reply. We are a client, and a server has sent this
      message
      * in response to a request. (server2client())
      * COPYDATA_EXPR:
      * An expression. We are a server, and a client wants us to
      * evaluate this expression.
      * COPYDATA_RESULT:
      * A reply. We are a client, and a server has sent this
      message
      * in response to a COPYDATA_EXPR.
      * COPYDATA_ERROR_RESULT:
      * A reply. We are a client, and a server has sent this
      message
      * in response to a COPYDATA_EXPR that failed to evaluate.
      */
      COPYDATASTRUCT *data = (COPYDATASTRUCT*)lParam;
      HWND sender = (HWND)wParam;
      COPYDATASTRUCT reply;
      char_u *res;
      char_u winstr[30];
      int retval;
      + int debug_break_level_save = debug_break_level;
      + BOOL redir_off_save = redir_off;


      switch (data->dwData)
      {
      case COPYDATA_KEYS:
      /* Remember who sent this, for <client> */
      clientWindow = sender;

      /* Add the received keys to the input buffer. The loop
      waiting
      * for the user to do something should check the input
      buffer. */
      server_to_input_buf((char_u *)(data->lpData));

      # ifdef FEAT_GUI
      /* Wake up the main GUI loop. */
      if (s_hwnd != 0)
      PostMessage(s_hwnd, WM_NULL, 0, 0);
      # endif
      return 1;

      case COPYDATA_EXPR:
      /* Remember who sent this, for <client> */
      clientWindow = sender;

      ++emsg_skip;
      + debug_break_level = -1;
      + redir_off = 0;
      res = eval_to_string(data->lpData, NULL);
      + redir_off = redir_off_save;
      + debug_break_level = debug_break_level_save;
      --emsg_skip;
      if (res == NULL)
      {
      res = vim_strsave(_(e_invexprmsg));
      reply.dwData = COPYDATA_ERROR_RESULT;
      }
      else
      reply.dwData = COPYDATA_RESULT;
      reply.lpData = res;
      reply.cbData = STRLEN(res) + 1;

      retval = SendMessage(sender, WM_COPYDATA,
      (WPARAM)message_window,

      (LPARAM)(&reply));
      vim_free(res);
      return retval;

      case COPYDATA_REPLY:
      case COPYDATA_RESULT:
      case COPYDATA_ERROR_RESULT:
      if (data->lpData != NULL)
      {
      save_reply(sender, data->lpData,
      (data->dwData == COPYDATA_REPLY ? 0 :
      (data->dwData == COPYDATA_RESULT ? 1 :
      2)));
      #ifdef FEAT_AUTOCMD
      if (data->dwData == COPYDATA_REPLY)
      {
      sprintf((char *)winstr, "0x%x", (unsigned)sender);
      apply_autocmds(EVENT_REMOTEREPLY, winstr,
      data->lpData,
      TRUE,
      curbuf);
      }
      #endif
      }
      return 1;
      }

      return 0;
      }

      else if (msg == WM_ACTIVATE && wParam == WA_ACTIVE)
      {
      /* When the message window is activated (brought to the
      foreground),
      * this actually applies to the text window. */
      #ifndef FEAT_GUI
      GetConsoleHwnd(); /* get value of s_hwnd */
      #endif
      if (s_hwnd != 0)
      {
      SetForegroundWindow(s_hwnd);
      return 0;
      }
      }

      return DefWindowProc(hwnd, msg, wParam, lParam);
      }
    • Michael Geddes
      This is getting a bit gnarly, so I ll let somebody who has had more experience with this area have a go. I ve found the basic reason for the problem, which is
      Message 2 of 5 , Jul 1, 2003
        This is getting a bit gnarly, so I'll let somebody who has had more
        experience with this area have a go.

        I've found the basic reason for the problem, which is that within
        do_debug, it is doing an 'inchar' passing a pointer indexing into the
        global typebuf.tb_buf ... the problem is then that when you send a
        message via remote_send, this calls 'server_to_input_buf' which calls
        'ins_typebuf' which frees the memory pointed to by typebuf.tb_buf.

        Then when the original gui_mch_wait_for_chars returns, the 'buf'
        pointer passed in is pointing at freed memory.

        I believe this bug could happen in the normal remote_send (not in
        debug), but in this case, it appears to always reach the 'simple' case
        where there is enough room in the type-ahead buffer.

        (Steps to reproduce are still the same as the original mail in this
        thread - the second case).

        //.



        ins_typebuf(unsigned char * 0x00c42008, int 0xffffffff, int 0x00000000,
        int 0x00000001, int 0x00000000) line 954
        server_to_input_buf(unsigned char * 0x00c42008) line 3031 + 17 bytes
        Messaging_WndProc(HWND__ * 0x00130e9a, unsigned int 0x0000004a, unsigned
        int 0x000b0d3a, long 0x0012ef0c) line 2304 + 12 bytes
        USER32! 77d43a68()
        USER32! 77d43b37()
        USER32! 77d4450d()
        USER32! 77d4c3a9()
        NTDLL! 77fb4da6()
        process_message() line 1466
        gui_mch_wait_for_chars(int 0xffffffff) line 1738
        gui_wait_for_chars(long 0xffffffff) line 2609 + 7 bytes
        ui_inchar(unsigned char * 0x00c422a0, int 0x00000058, long 0xffffffff)
        line 165 + 9 bytes
        inchar(unsigned char * 0x00c422a0, int 0x00000108, long 0xffffffff) line
        2663 + 25 bytes
        vgetorpeek(int 0x00000001) line 2464 + 179 bytes
        vgetc() line 1421 + 7 bytes
        safe_vgetc() line 1552 + 5 bytes
        getcmdline(int 0x0000003e, long 0x00000001, int 0x00000000) line 285 + 5
        bytes
        getcmdline_prompt(int 0x0000003e, unsigned char * 0x00000000, int
        0x00000000) line 1628 + 13 bytes
        do_debug(unsigned char * 0x00c43240) line 113 + 11 bytes
        dbg_check_breakpoint(exarg * 0x0012f4fc) line 297 + 12 bytes
        do_one_cmd(unsigned char * * 0x0012f608, int 0x00000001, condstack *
        0x0012f614, unsigned char * (int, void *, int)* 0x00000000, void *
        0x00000000) line 1483 + 9 bytes
        do_cmdline(unsigned char * 0x00c439ee, unsigned char * (int, void *,
        int)* 0x00000000, void * 0x00000000, int 0x0000000b) line 873 + 34 bytes
        do_cmdline_cmd(unsigned char * 0x00c439ee) line 548 + 15 bytes
        ex_debug(exarg * 0x0012f8bc) line 239 + 11 bytes

        -----Original Message-----
        From: Michael Geddes
        Sent: Wednesday, 2 July 2003 12:00 PM
        To: Hari Krishna Dara
        Cc: Vim-dev@...
        Subject: RE: remote debugging ideas for vimscripts


        Hari et al,

        I think the remote debugging idea is quite kool.. so I've done a bit of
        digging.

        As a start, I suggest that we turn off debug mode and redir_off at
        the start of the
        message handler for remote_expr() on the server and restore them at the
        end.

        In os_mswin.c.. this is done by adding the + lines in the code block
        below. This fixed problem number 1.. which is that the call doesn't
        return until you type 'cont' on the server. I've also checked that you
        can still :breakadd the function that is being called to allow debugging
        of remote calls.

        The second problem I haven't got much info on.. or time to do it.
        However running the debug version under msdev debugger, I'm seeing:

        HEAP[gvimd.exe]: HEAP: Free Heap block c41610 modified at c41638
        after it was freed

        on the server when you type

        :call remote_send('GVIMD', ":let @z=GetVimCmdOutput('ls')\<CR>")

        on the client vim... which isn't very promising. If I do get time I'll
        investigate!

        //.





        //.
        ----------8<---------------

        static LRESULT CALLBACK
        Messaging_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
        if (msg == WM_COPYDATA)
        {
        /* This is a message from another Vim. The dwData member of the
        * COPYDATASTRUCT determines the type of message:
        * COPYDATA_KEYS:
        * A key sequence. We are a server, and a client wants
        these keys
        * adding to the input queue.
        * COPYDATA_REPLY:
        * A reply. We are a client, and a server has sent this
        message
        * in response to a request. (server2client())
        * COPYDATA_EXPR:
        * An expression. We are a server, and a client wants us to
        * evaluate this expression.
        * COPYDATA_RESULT:
        * A reply. We are a client, and a server has sent this
        message
        * in response to a COPYDATA_EXPR.
        * COPYDATA_ERROR_RESULT:
        * A reply. We are a client, and a server has sent this
        message
        * in response to a COPYDATA_EXPR that failed to evaluate.
        */
        COPYDATASTRUCT *data = (COPYDATASTRUCT*)lParam;
        HWND sender = (HWND)wParam;
        COPYDATASTRUCT reply;
        char_u *res;
        char_u winstr[30];
        int retval;
        + int debug_break_level_save = debug_break_level;
        + BOOL redir_off_save = redir_off;


        switch (data->dwData)
        {
        case COPYDATA_KEYS:
        /* Remember who sent this, for <client> */
        clientWindow = sender;

        /* Add the received keys to the input buffer. The loop
        waiting
        * for the user to do something should check the input
        buffer. */
        server_to_input_buf((char_u *)(data->lpData));

        # ifdef FEAT_GUI
        /* Wake up the main GUI loop. */
        if (s_hwnd != 0)
        PostMessage(s_hwnd, WM_NULL, 0, 0);
        # endif
        return 1;

        case COPYDATA_EXPR:
        /* Remember who sent this, for <client> */
        clientWindow = sender;

        ++emsg_skip;
        + debug_break_level = -1;
        + redir_off = 0;
        res = eval_to_string(data->lpData, NULL);
        + redir_off = redir_off_save;
        + debug_break_level = debug_break_level_save;
        --emsg_skip;
        if (res == NULL)
        {
        res = vim_strsave(_(e_invexprmsg));
        reply.dwData = COPYDATA_ERROR_RESULT;
        }
        else
        reply.dwData = COPYDATA_RESULT;
        reply.lpData = res;
        reply.cbData = STRLEN(res) + 1;

        retval = SendMessage(sender, WM_COPYDATA,
        (WPARAM)message_window,

        (LPARAM)(&reply));
        vim_free(res);
        return retval;

        case COPYDATA_REPLY:
        case COPYDATA_RESULT:
        case COPYDATA_ERROR_RESULT:
        if (data->lpData != NULL)
        {
        save_reply(sender, data->lpData,
        (data->dwData == COPYDATA_REPLY ? 0 :
        (data->dwData == COPYDATA_RESULT ? 1 :
        2)));
        #ifdef FEAT_AUTOCMD
        if (data->dwData == COPYDATA_REPLY)
        {
        sprintf((char *)winstr, "0x%x", (unsigned)sender);
        apply_autocmds(EVENT_REMOTEREPLY, winstr,
        data->lpData,
        TRUE,
        curbuf);
        }
        #endif
        }
        return 1;
        }

        return 0;
        }

        else if (msg == WM_ACTIVATE && wParam == WA_ACTIVE)
        {
        /* When the message window is activated (brought to the
        foreground),
        * this actually applies to the text window. */
        #ifndef FEAT_GUI
        GetConsoleHwnd(); /* get value of s_hwnd */
        #endif
        if (s_hwnd != 0)
        {
        SetForegroundWindow(s_hwnd);
        return 0;
        }
        }

        return DefWindowProc(hwnd, msg, wParam, lParam);
        }
      • Bram Moolenaar
        ... Thanks for figuring it out this far. It s really a problem of the event handling doing something unexpected. It is not obvious how this should be fixed.
        Message 3 of 5 , Jul 2, 2003
          Michael Geddes wrote:

          > This is getting a bit gnarly, so I'll let somebody who has had more
          > experience with this area have a go.
          >
          > I've found the basic reason for the problem, which is that within
          > do_debug, it is doing an 'inchar' passing a pointer indexing into the
          > global typebuf.tb_buf ... the problem is then that when you send a
          > message via remote_send, this calls 'server_to_input_buf' which calls
          > 'ins_typebuf' which frees the memory pointed to by typebuf.tb_buf.
          >
          > Then when the original gui_mch_wait_for_chars returns, the 'buf'
          > pointer passed in is pointing at freed memory.
          >
          > I believe this bug could happen in the normal remote_send (not in
          > debug), but in this case, it appears to always reach the 'simple' case
          > where there is enough room in the type-ahead buffer.
          >
          > (Steps to reproduce are still the same as the original mail in this
          > thread - the second case).

          Thanks for figuring it out this far. It's really a problem of the event
          handling doing something unexpected. It is not obvious how this should
          be fixed. I'll add a remark in the todo list.

          --
          Eight Megabytes And Continually Swapping.

          /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
          /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
          \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
          \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///
        • Bram Moolenaar
          ... That makes sense in most situations, but what if the user really wants to debug the commands being send remotely? -- The psychic said, God bless you. I
          Message 4 of 5 , Jul 2, 2003
            Michael Geddes wrote:

            > I think the remote debugging idea is quite kool.. so I've done a bit of
            > digging.
            >
            > As a start, I suggest that we turn off debug mode and redir_off at
            > the start of the message handler for remote_expr() on the server and
            > restore them at the end.

            That makes sense in most situations, but what if the user really wants
            to debug the commands being send remotely?

            --
            The psychic said, "God bless you." I said, "I didn't sneeze." She
            looked deep into my eyes and said, "You will, eventually." And, damn
            if she wasn't right. Two days later, I sneezed. --Ellen Degeneres

            /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
            /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
            \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
            \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///
          • Michael Geddes
            That works. Even with this patch, if you :breakadd the function being called, then it will break back into the debugger as expected (very nice, I thought)! We
            Message 5 of 5 , Jul 2, 2003
              That works.

              Even with this patch, if you :breakadd the function being called, then
              it will break back into the debugger as expected (very nice, I thought)!

              We could always add support for doing
              :breakadd func remote_expr
              that would cause the debugger to run on any remote_expr, which would
              then go into debug mode whether we were in debug mode originally or not!
              This, I believe, would be MUCH prefereable.

              //.ichael G.

              -----Original Message-----
              From: Bram Moolenaar [mailto:Bram@...]
              Sent: Thursday, 3 July 2003 6:15 AM
              To: Michael Geddes
              Cc: Hari Krishna Dara; Vim-dev@...
              Subject: RE: remote debugging ideas for vimscripts



              Michael Geddes wrote:

              > I think the remote debugging idea is quite kool.. so I've done a bit
              > of digging.
              >
              > As a start, I suggest that we turn off debug mode and redir_off at
              > the start of the message handler for remote_expr() on the server and
              > restore them at the end.

              That makes sense in most situations, but what if the user really wants
              to debug the commands being send remotely?

              --
              The psychic said, "God bless you." I said, "I didn't sneeze." She
              looked deep into my eyes and said, "You will, eventually." And, damn if
              she wasn't right. Two days later, I sneezed. --Ellen Degeneres

              /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net
              \\\
              /// Creator of Vim - Vi IMproved -- http://www.Vim.org
              \\\
              \\\ Project leader for A-A-P -- http://www.A-A-P.org
              ///
              \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html
              ///
            Your message has been successfully submitted and would be delivered to recipients shortly.