Browse Source

Merge pull request #10717 from jakesmith/hpcc-18863

HPCC-18863 Add a getAllStacks() function.

Reviewed-by: Gavin Halliday <ghalliday@hpccsystems.com>
Gavin Halliday 7 years ago
parent
commit
f68bc099f5

+ 1 - 11
common/remote/hooks/git/gitfile.cpp

@@ -86,17 +86,7 @@ public:
         if (pipe->run("git", gitcmd, ".", false, true, false, 0))
         {
             Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
-            const size32_t chunkSize = 8192;
-            for (;;)
-            {
-                size32_t sizeRead = pipeReader->read(chunkSize, buf.reserve(chunkSize));
-                if (sizeRead < chunkSize)
-                {
-                    buf.setLength(buf.length() - (chunkSize - sizeRead));
-                    if (!sizeRead)
-                        break;
-                }
-            }
+            readSimpleStream(buf, *pipeReader);
             pipe->closeOutput();
         }
         int retcode = pipe->wait();

+ 1 - 10
ecl/eclcc/eclcc.cpp

@@ -1715,16 +1715,7 @@ void EclCC::generateOutput(EclCompileInstance & instance)
                             unsigned retcode = pipe->wait();
                             StringBuffer buf;
                             Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
-                            const size32_t chunkSize = 128;
-                            for (;;)
-                            {
-                                size32_t sizeRead = pipeReader->read(chunkSize, buf.reserve(chunkSize));
-                                if (sizeRead < chunkSize)
-                                {
-                                    buf.setLength(buf.length() - (chunkSize - sizeRead));
-                                    break;
-                                }
-                            }
+                            readSimpleStream(buf, *pipeReader, 128);
                             if (retcode)
                                 WARNLOG("Failed to run git describe: returned %d (%s)", retcode, buf.str());
                             else if (buf.length())

+ 1 - 10
ecl/hql/hqlexpr.ipp

@@ -517,16 +517,7 @@ public:
                         unsigned retcode = pipe->wait();
                         StringBuffer buf;
                         Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
-                        const size32_t chunkSize = 128;
-                        for (;;)
-                        {
-                            size32_t sizeRead = pipeReader->read(chunkSize, buf.reserve(chunkSize));
-                            if (sizeRead < chunkSize)
-                            {
-                                buf.setLength(buf.length() - (chunkSize - sizeRead));
-                                break;
-                            }
-                        }
+                        readSimpleStream(buf, *pipeReader, 128);
                         if (retcode)
                             WARNLOG("Failed to run git status for %s: returned %d (%s)", sourcePath->queryStr(), retcode, buf.str());
                         else if (buf.length())

+ 1 - 10
ecl/hql/hqlparse.cpp

@@ -620,16 +620,7 @@ void HqlLex::checkSignature(const attribute & dummyToken)
 
         StringBuffer buf;
         Owned<ISimpleReadStream> pipeReader = pipe->getErrorStream();
-        const size32_t chunkSize = 8192;
-        for (;;)
-        {
-            size32_t sizeRead = pipeReader->read(chunkSize, buf.reserve(chunkSize));
-            if (sizeRead < chunkSize)
-            {
-                buf.setLength(buf.length() - (chunkSize - sizeRead));
-                break;
-            }
-        }
+        readSimpleStream(buf, *pipeReader);
         DBGLOG("GPG %d %s", retcode, buf.str());
         if (retcode)
         {

+ 25 - 0
system/jlib/jexcept.cpp

@@ -1452,6 +1452,31 @@ void printStackReport(__int64 startIP)
 
 //---------------------------------------------------------------------------------------------------------------------
 
+bool getAllStacks(StringBuffer &output)
+{
+#ifdef __linux__
+    const char *exePath = queryCurrentProcessPath();
+    if (!exePath)
+    {
+        output.append("Unable to capture stacks");
+        return false;
+    }
+    VStringBuffer cmd("gdb --batch -n -ex 'thread apply all bt' %s %u", exePath, GetCurrentProcessId());
+    Owned<IPipeProcess> pipe = createPipeProcess();
+    if (pipe->run("get stacks", cmd, nullptr, false, true, false))
+    {
+        Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
+        readSimpleStream(output, *pipeReader);
+    }
+    int retcode = pipe->wait();
+    return 0 == retcode;
+#else
+    return false; // unsupported
+#endif
+}
+
+//---------------------------------------------------------------------------------------------------------------------
+
 class jlib_decl CError : public CInterfaceOf<IError>
 {
 public:

+ 2 - 0
system/jlib/jexcept.hpp

@@ -148,6 +148,8 @@ void  jlib_decl printStackReport(__int64 startIP = 0);
 // Macro for legacy name of above function
 #define PrintStackReport printStackReport
 
+bool jlib_decl getAllStacks(StringBuffer &output);
+
 #ifdef _DEBUG
 #define RELEASE_CATCH_ALL       int*********
 #else

+ 20 - 0
system/jlib/jio.cpp

@@ -1350,3 +1350,23 @@ void writeStringToStream(IIOStream &out, const char *s) { out.write((size32_t)st
 void writeCharsNToStream(IIOStream &out, char c, unsigned cnt) { while(cnt--) out.write(1, &c); }
 void writeCharToStream(IIOStream &out, char c) { out.write(1, &c); }
 #endif
+
+template<typename T> size32_t readSimpleStream(T &target, ISimpleReadStream &stream, size32_t readChunkSize)
+{
+    size32_t totalSz = 0;
+    while (true)
+    {
+        size32_t sizeRead = stream.read(readChunkSize, target.reserve(readChunkSize));
+        if (sizeRead < readChunkSize)
+        {
+            target.setLength(target.length() - (readChunkSize - sizeRead));
+            if (!sizeRead)
+                break;
+        }
+        totalSz += sizeRead;
+    }
+    return totalSz;
+}
+template size32_t readSimpleStream<StringBuffer>(StringBuffer &, ISimpleReadStream &, size32_t);
+template size32_t readSimpleStream<MemoryBuffer>(MemoryBuffer &, ISimpleReadStream &, size32_t);
+

+ 5 - 0
system/jlib/jio.hpp

@@ -22,6 +22,7 @@
 
 #include "jiface.hpp"
 #include "jarray.hpp"
+#include "jbuff.hpp"
 #include <stdio.h>
 
 typedef count_t findex_t;       //row index in a file.
@@ -77,6 +78,10 @@ interface IIOStream : public ISimpleReadStream
     virtual size32_t write(size32_t len, const void * data) = 0;
 };
 
+template<typename T> size32_t readSimpleStream(T &target, ISimpleReadStream &stream, size32_t readChunkSize = 8192);
+extern template jlib_decl size32_t readSimpleStream<StringBuffer>(StringBuffer &, ISimpleReadStream &, size32_t);
+extern template jlib_decl size32_t readSimpleStream<MemoryBuffer>(MemoryBuffer &, ISimpleReadStream &, size32_t);
+
 
 #ifdef  __x86_64__
 extern jlib_decl  void writeStringToStream(IIOStream &out, const char *s);

+ 8 - 0
thorlcr/graph/thgraph.cpp

@@ -2736,6 +2736,14 @@ void CJobBase::startJob()
         keyFileCacheLimit = (querySlaves()+1)*2;
     setKeyIndexCacheSize(keyFileCacheLimit);
     PROGLOG("Key file cache size set to: %d", keyFileCacheLimit);
+    if (getOptBool("dumpStacks")) // mainly as an example of printAllStacks() usage
+    {
+        StringBuffer output;
+        if (getAllStacks(output))
+            PrintLogDirect(output);
+        else
+            WARNLOG("Failed to capture process stacks: %s", output.str());
+    }
 }
 
 void CJobBase::endJob()

+ 1 - 10
tools/initldap/initldap.cpp

@@ -193,16 +193,7 @@ int main(int argc, char* argv[])
         if (pipe->run("configgen", cmd.str(), ".", false, true, true, 0))
         {
             Owned<ISimpleReadStream> pipeReader = pipe->getOutputStream();
-            const size32_t chunkSize = 8192;
-            for (;;)
-            {
-                size32_t sizeRead = pipeReader->read(chunkSize, configBuff.reserve(chunkSize));
-                if (sizeRead < chunkSize)
-                {
-                    configBuff.setLength(configBuff.length() - (chunkSize - sizeRead));
-                    break;
-                }
-            }
+            readSimpleStream(configBuff, *pipeReader);
             pipe->closeOutput();
         }
         int retcode = pipe->wait();