octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Handle leak in win32 patch to readline


From: Benjamin Lindner
Subject: Handle leak in win32 patch to readline
Date: Fri, 30 Jan 2009 19:53:46 +0100
User-agent: Thunderbird 2.0.0.18 (Windows/20081105)

Hello list,

I am posting this here, because I discovered the handle leak while testing mingw binaries for the octave development sources, although I tracked down the leak to be technically outside octave. Anyway, in the win32-specific patchfile Michael created for compiling libreadline - which I shamelessly reused for mingw32 - I think there are two calls to CloseHandle() missing in in input.c.

Michael, Tatsuro, I guess we are the ones that will be affected, since cygwin has a version of libreadline of its own, IIRC.

Sigh, now a diff to a diff is virtually inlegibile, since I slightly modified michael's original patch to also apply to mingw32 (basically looking at the #ifdef _MSC_VER and adding a defined __MINGW32__). Now I tried to read the diff-to-a-diff, but gave up.

I have attached the part of my mingw32 patch to readline, and cropped out the relevant part.

In this patch see lines 58 and 161. Immediatly after the call to
  GetExitCodeThread (tty_reader_thread, (LPDWORD)&k);
and
  GetExitCodeThread (tty_reader_thread, (LPDWORD)&ch);
respectively, I added a
  CloseHandle(tty_reader_thread)
in both cases.

I hope you can follow my description...

You can also check on the octave-forge svn repository for the log of readline/readline-5.2-3.patch.

Michael, for our msvc/mingw build framework, we must merge the patches (if present) to single both-applicable-on-msvc-and-mingw patches.
This one got me *really* confused...

benjamin
diff -urN -x '*.exe' -x '*.dll' -x '*.o' -x '*.a' -x '*.bak' 
readline-5.2-orig/input.c readline-5.2/input.c
--- readline-5.2-orig/input.c   2006-08-16 19:15:16 +0000
+++ readline-5.2/input.c        2009-01-30 11:23:53 +0000
@@ -221,13 +404,71 @@
     }
 #endif /* O_NDELAY */
 
-#if defined (__MINGW32__)
+#if !defined (__MINGW32__) && !defined (_MSC_VER)
   /* Use getch/_kbhit to check for available console input, in the same way
      that we read it normally. */
    chars_avail = isatty (tty) ? _kbhit () : 0;
    result = 0;
 #endif
 
+#if defined (_MSC_VER) || defined(__MINGW32__)
+   if (isatty (tty) || 1)
+     {
+#if 0
+       HANDLE hInput = _get_osfhandle (tty);
+       INPUT_RECORD rec;
+       DWORD evRead, waitResult;
+
+       do
+         {
+          waitResult = WaitForSingleObject(hInput, 
_keyboard_input_timeout/1000);
+          if (waitResult == WAIT_TIMEOUT)
+            return (0);
+          else if (waitResult == WAIT_OBJECT_0)
+            {
+              if (PeekConsoleInput(hInput, &rec, 1, &evRead) && evRead == 1)
+              {
+                if (rec.EventType == KEY_EVENT && rec.Event.KeyEvent.bKeyDown)
+                  {
+                    chars_avail = 1;
+                    result = 0;
+                    break;
+                  }
+                else
+                  ReadConsoleInput(hInput, &rec, 1, &evRead);
+              }
+            }
+         }
+       while (1);
+#else
+       DWORD waitResult;
+       int is_tty = isatty (tty);
+
+       if (tty_reader_thread == NULL)
+         tty_reader_thread = CreateThread (NULL, 0, tty_reader_proc,
+             (LPVOID)is_tty, 0, NULL);
+       waitResult = WaitForMultipleObjects (1, &tty_reader_thread, FALSE, 
_keyboard_input_timeout/1000);
+       if (waitResult == WAIT_TIMEOUT)
+         return 0;
+       else if (waitResult == WAIT_OBJECT_0)
+         {
+           GetExitCodeThread (tty_reader_thread, (LPDWORD)&k);
==>+           CloseHandle(tty_reader_thread);
+           tty_reader_thread = NULL;
+           rl_stuff_char (k);
+           return 1;
+         }
+       else
+         return -1;
+#endif
+     }
+   else
+     {
+       chars_avail = 0;
+       result = 0;
+     }
+#endif
+
   /* If there's nothing available, don't waste time trying to read
      something. */
   if (chars_avail <= 0)
@@ -459,9 +700,99 @@
     {
 #if defined (__MINGW32__)
       if (isatty (fileno (stream)))
-       return (getch ());
-#endif
-      result = read (fileno (stream), &c, sizeof (unsigned char));
+#if defined (_MSC_VER) || defined(__MINGW32__)
+        {
+#if 0
+          INPUT_RECORD rec;
+         DWORD evRead;
+         HANDLE hInput = _get_osfhandle (fileno (stream));
+
+         do {
+            if (!ReadConsoleInput(hInput, &rec, 1, &evRead) || evRead != 1)
+             return EOF;
+           switch (rec.EventType)
+             {
+               case KEY_EVENT:
+                 if (rec.Event.KeyEvent.bKeyDown &&
+                     (rec.Event.KeyEvent.wVirtualKeyCode < VK_SHIFT ||
+                      rec.Event.KeyEvent.wVirtualKeyCode > VK_MENU))
+                   {
+                     if (rec.Event.KeyEvent.uChar.AsciiChar)
+                        {
+                          if (rec.Event.KeyEvent.uChar.AsciiChar < 0)
+                            {
+                              char ch1[2] = {0};
+                              char ch2[2] = {0};
+                              ch1[0] = rec.Event.KeyEvent.uChar.AsciiChar;
+                              OemToChar(ch1, ch2);
+                              return ch2[0];
+                            }
+                          else
+                            return rec.Event.KeyEvent.uChar.UnicodeChar;
+                        }
+                     else
+                       switch (rec.Event.KeyEvent.wVirtualKeyCode)
+                         {
+                           case VK_UP:
+                             rl_execute_next ('H');
+                             return 0340;
+                           case VK_DOWN:
+                             rl_execute_next ('P');
+                             return 0340;
+                           case VK_RIGHT:
+                             rl_execute_next ('M');
+                             return 0340;
+                           case VK_LEFT:
+                             rl_execute_next ('K');
+                             return 0340;
+                           case VK_HOME:
+                             rl_execute_next ('G');
+                             return 0340;
+                           case VK_END:
+                             rl_execute_next ('O');
+                             return 0340;
+                           case VK_DELETE:
+                             rl_execute_next ('S');
+                             return 0340;
+                           default:
+                             break;
+                         }
+                   }
+                 break;
+               default:
+                 break;
+             }
+         } while (1);
+#else  /* #if 0 */
+          if (tty_reader_thread != NULL)
+            {
+              /* this may happen after resetting the event proc to NULL
+               * while the reader thread was still running
+               */
+              DWORD waitResult;
+
+              waitResult = WaitForSingleObject (tty_reader_thread, INFINITE);
+              if (waitResult == WAIT_OBJECT_0)
+                {
+                  int ch;
+
+                  GetExitCodeThread (tty_reader_thread, (LPDWORD)&ch);
==>+                  CloseHandle(tty_reader_thread);
+                  tty_reader_thread = NULL;
+                  return ch;
+                }
+              else
+                return (EOF);
+            }
+          else
+            return (win32_getch ());
+#endif /* if 0 */
+       }
+#else  /* #if defined (_MSC_VER) || defined(__MINGW32__) */
+       return (_getch ());
+#endif /* #if defined (_MSC_VER) || defined(__MINGW32__) */
+#endif /* #if defined (__MINGW32__) */
+      result = win32_read (fileno (stream), &c, sizeof (unsigned char));
 
       if (result == sizeof (unsigned char))
        return (c);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]