Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERR_SOCKET_DGRAM_NOT_RUNNING error when chunking request body(fix suggested) #78

Closed
Hsiwe opened this issue Jun 7, 2022 · 1 comment

Comments

@Hsiwe
Copy link

Hsiwe commented Jun 7, 2022

Hi! I'm using gelf-pro as a tool to send my app's logs through UDP. Recently I started to get ERR_SOCKET_DGRAM_NOT_RUNNING exception from time to time.
Here's an error trace:

Error [ERR_SOCKET_DGRAM_NOT_RUNNING]: Not running
at new NodeError (node:internal/errors:363:5)
    at healthCheck (node:dgram:908:11)
    at Socket.close (node:dgram:740:3)
    at cbResults (path/to/my/app/node_modules/gelf-pro/lib/adapter/udp.js:75:14)
    at /path/to/my/app/node_modules/gelf-pro/lib/adapter/udp.js:118:13
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

As specified in the stack trace - the error happens when Socket.close is called.
After investigation I found that this happens only when request body is more than 1388 bytes and gelf-pro divides body in chunks.
The bug is in this code(from /lib/adapter/udp.js:103):

for (var idx in chunks) {
      if (isInterrupted) {
        break;
      }
      var chunk = chunks[idx],
        packet = buffer
          .from(self.specification.magicBytes.concat(packetId, idx, chunksCount, chunk));
      client.send(
        packet, 0, packet.length, self.options.port, self.options.host,
        function (err, bytesSent) {
          if (err) { return cbResults(err); }
          bytesSentTotal += bytesSent;
          /* istanbul ignore else */
          if (idx >= chunksCount - 1) {
            cbResults(err, bytesSentTotal);
          }
        }
      );
    }

More specifically in this closure:

if (idx >= chunksCount - 1) {
            cbResults(err, bytesSentTotal);
          }

Here idx is specified to check whether we arrived at the end of chunks array or not, but because of how JavaScript variable scope works what actually happens is - idx is always equal to chunksCount - 1 and cbResults is called on every loop, not only on the last one (hence ERR_SOCKET_DGRAM_NOT_RUNNING error because we try to close udp connection multiple times). Great example of how and why it works like this is provided here.

So here's a fix I came up with. What's important to note - in order for this fix to work you must use const(or let), not var(because var variable are not scope bound and by using var we actually do the same thing).

diff --git a/node_modules/gelf-pro/lib/adapter/udp.js b/node_modules/gelf-pro/lib/adapter/udp.js
index 58e452d..431b38c 100644
--- a/node_modules/gelf-pro/lib/adapter/udp.js
+++ b/node_modules/gelf-pro/lib/adapter/udp.js
@@ -101,20 +101,21 @@ adapter.send = function (message, callback) {
 
     var packetId = Array.prototype.slice.call(crypto.randomBytes(8));
     for (var idx in chunks) {
+      const capturedIndex = idx;
       if (isInterrupted) {
         break;
       }
       var chunk = chunks[idx],
         packet = buffer
           .from(self.specification.magicBytes.concat(packetId, idx, chunksCount, chunk));
       client.send(
         packet, 0, packet.length, self.options.port, self.options.host,
         function (err, bytesSent) {
           if (err) { return cbResults(err); }
           bytesSentTotal += bytesSent;
           /* istanbul ignore else */
-          if (idx >= chunksCount - 1) {
+          if (capturedIndex >= chunksCount - 1) {
             cbResults(err, bytesSentTotal);
           }
         }

This issue body was partially generated by patch-package.

@kkamkou kkamkou closed this as completed in 2bbe87a Jun 8, 2022
@kkamkou
Copy link
Owner

kkamkou commented Jun 8, 2022

Thank you for the detailed report and a hint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants