[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

RE: The WindowsBufferProblems



The patch below adds some extra logging when the problem occurs. Could it
please be added so we can get some more data on exactly what's going on?

Gé van Geldorp.

Index: src/common/tortls.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/common/tortls.c,v
retrieving revision 1.123
diff -u -r1.123 tortls.c
--- src/common/tortls.c	7 Jun 2006 06:21:09 -0000	1.123
+++ src/common/tortls.c	17 Jun 2006 20:05:30 -0000
@@ -22,6 +22,7 @@
 #include "./util.h"
 #include "./log.h"
 #include <string.h>
+#include <stdio.h> /* Only needed for WSAENOBUFS debug funcs */
 
 /* Copied from or.h */
 #define LEGAL_NICKNAME_CHARACTERS \
@@ -101,6 +102,159 @@
   }
 }
 
+#ifdef MS_WINDOWS
+/** Get amount of used NonPagedPool memory
+ * Uses function and structure only documented in Gary Nebbett's
+ * "Native API reference". Should be ok to use, known to work on
+ * all NT derived (NT4, Win2k, XP, Win2k3, Vista) Windows versions.
+ * Besides, if the function is not available, we fail gracefully.
+ */
+static unsigned long
+GetNonPagedPoolUsageKb( )
+  {
+  typedef int (__stdcall *QUERYSYSTEMINFORMATIONPROC)(int, PVOID, ULONG,
PULONG);
+  typedef struct _SYSTEM_PERFORMANCE_INFORMATION
+  {
+    LARGE_INTEGER IdleTime;
+    LARGE_INTEGER ReadTransferCount;
+    LARGE_INTEGER WriteTransferCount;
+    LARGE_INTEGER OtherTransferCount;
+    ULONG ReadOperationCount;
+    ULONG WriteOperationCount;
+    ULONG OtherOperationCount;
+    ULONG AvailablePages;
+    ULONG TotalCommittedPages;
+    ULONG TotalCommitLimit;
+    ULONG PeakCommitment;
+    ULONG PageFaults;
+    ULONG WriteCopyFaults;
+    ULONG TransitionFaults;
+    ULONG Reserved1;
+    ULONG DemandZeroFaults;
+    ULONG PagesRead;
+    ULONG PageReadIos;
+    ULONG Reserved2[2];
+    ULONG PagefilePagesWritten;
+    ULONG PagefilePageWriteIos;
+    ULONG MappedFilePagesWritten;
+    ULONG MappedFilePageWriteIos;
+    ULONG PagedPoolUsage;
+    ULONG NonPagedPoolUsage;
+    ULONG PagedPoolAllocs;
+    ULONG PagedPoolFrees;
+    ULONG NonPagedPoolAllocs;
+    ULONG NonPagedPoolFrees;
+    ULONG TotalFreeSystemPtes;
+    ULONG SystemCodePage;
+    ULONG TotalSystemDriverPages;
+    ULONG TotalSystemCodePages;
+    ULONG SmallNonPagedLookasideListAllocateHits;
+    ULONG SmallPagedLookasideListAllocateHits;
+    ULONG Reserved3;
+    ULONG MmSystemCachePage;
+    ULONG PagedPoolPage;
+    ULONG SystemDriverPage;
+    ULONG FastReadNoWait;
+    ULONG FastReadWait;
+    ULONG FastReadResourceMiss;
+    ULONG FastReadNotPossible;
+    ULONG FastMdlReadNoWait;
+    ULONG FastMdlReadWait;
+    ULONG FastMdlReadResourceMiss;
+    ULONG FastMdlReadNotPossible;
+    ULONG MapDataNoWait;
+    ULONG MapDataWait;
+    ULONG MapDataNoWaitMiss;
+    ULONG MapDataWaitMiss;
+    ULONG PinMappedDataCount;
+    ULONG PinReadNoWait;
+    ULONG PinReadWait;
+    ULONG PinReadNoWaitMiss;
+    ULONG PinReadWaitMiss;
+    ULONG CopyReadNoWait;
+    ULONG CopyReadWait;
+    ULONG CopyReadNoWaitMiss;
+    ULONG CopyReadWaitMiss;
+    ULONG MdlReadNoWait;
+    ULONG MdlReadWait;
+    ULONG MdlReadNoWaitMiss;
+    ULONG MdlReadWaitMiss;
+    ULONG ReadAheadIos;
+    ULONG LazyWriteIos;
+    ULONG LazyWritePages;
+    ULONG DataFlushes;
+    ULONG DataPages;
+    ULONG ContextSwitches;
+    ULONG FirstLevelTbFills;
+    ULONG SecondLevelTbFills;
+    ULONG SystemCalls;
+  } SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION;
+  static HMODULE ModNtDll = NULL;
+  static QUERYSYSTEMINFORMATIONPROC QSIProc = NULL;
+  SYSTEM_PERFORMANCE_INFORMATION SPI;
+
+  if (ModNtDll == NULL) {
+    ModNtDll = LoadLibrary("NTDLL.DLL");
+    if (ModNtDll == NULL)
+      return 0;
+  }
+  if (QSIProc == NULL) {
+    QSIProc = (QUERYSYSTEMINFORMATIONPROC)
+              GetProcAddress(ModNtDll, "NtQuerySystemInformation");
+    if (QSIProc == NULL) {
+      FreeLibrary(ModNtDll);
+      ModNtDll = NULL;
+      return 0;
+    }
+  }
+
+  if (( *QSIProc )(2, &SPI, sizeof(SYSTEM_PERFORMANCE_INFORMATION), NULL)
!= 0) {
+    FreeLibrary(ModNtDll);
+    QSIProc = NULL;
+    ModNtDll = NULL;
+    return 0;
+  }
+
+  return SPI.NonPagedPoolUsage * 4;
+}
+
+/** Temporary function to log some extra information to help track down
+ * the WSAENOBUFS error which is sometimes generated on Windows
+ */
+static void
+report_wsaenobufs(const char *doing)
+{
+  static unsigned report_count = 0;
+  FILE *netstat;
+  char buffer[81];
+
+  /* Don't flood the log */
+  if (10 <= report_count++) {
+    return;
+  }
+
+  log(LOG_WARN, LD_NET, "You just experienced the infamous WSAENOBUFS
condition, "
+      "please report and include the following info:");
+  log(LOG_WARN, LD_NET, "NonPaged Pool in use: %lu kB",
GetNonPagedPoolUsageKb());
+
+  /* Run netstat and include its output in the log */
+  netstat = _popen("netstat -np tcp", "rt");
+  if (netstat != NULL) {
+    log(LOG_WARN, LD_NET, "netstat:");
+    while (fgets(buffer, sizeof(buffer), netstat) != NULL) {
+      /* strip off the trailing \n */
+      if (buffer[strlen(buffer) - 1] == '\n')
+        buffer[strlen(buffer) - 1] = '\0';
+      log(LOG_WARN, LD_NET, "%s", buffer);
+    }
+    fclose(netstat);
+  } else
+    log(LOG_WARN, LD_NET, "Unable to read netstat info");
+
+  log(LOG_WARN, LD_NET, "End of WSAENOBUFS report");
+}
+#endif
+
 #define CATCH_SYSCALL 1
 #define CATCH_ZERO    2
 
@@ -136,6 +290,11 @@
         log(severity, LD_NET,
             "TLS error: <syscall error while %s> (errno=%d: %s)",
             doing, e, tor_socket_strerror(e));
+#ifdef MS_WINDOWS
+        if (e == WSAENOBUFS) {
+          report_wsaenobufs(doing);
+        }
+#endif
       }
       tls_log_errors(severity, doing);
       return TOR_TLS_ERROR;