संभावित EventEmitter स्मृति रिसाव का पता चला


231

मुझे चेतावनी मिल रही है:

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace: 
    at EventEmitter.<anonymous> (events.js:139:15)
    at EventEmitter.<anonymous> (node.js:385:29)
    at Server.<anonymous> (server.js:20:17)
    at Server.emit (events.js:70:17)
    at HTTPParser.onIncoming (http.js:1514:12)
    at HTTPParser.onHeadersComplete (http.js:102:31)
    at Socket.ondata (http.js:1410:22)
    at TCP.onread (net.js:354:27)

मैंने server.js में इस तरह कोड लिखा था:

http.createServer(
    function (req, res) { ... }).listen(3013);

इसे कैसे ठीक करें?


46
process.on('warning', e => console.warn(e.stack));चेतावनी को डीबग करने के लिए उपयोग करें । process.setMaxListeners(0);किसी कारण से चेतावनी का उपयोग न करें ।
श्वेताभ शेखर

धन्यवाद। बहुत उपयोगी निर्देश।
अब्दुल्ला अल फारूक

यह त्रुटि मुझ पर होती है yarn install। स्टैक ट्रेस जोड़ने के लिए मैं इस लाइन को कहाँ रख सकता हूँ?
सोनिक सोल

जवाबों:


94

यह नोड EventEmitter प्रलेखन में समझाया गया है

नोड का यह कौन सा संस्करण है? आपके पास और क्या कोड है? यह सामान्य व्यवहार नहीं है।

संक्षेप में, इसके: process.setMaxListeners(0);

इसे भी देखें: नोड.जेएस - अनुरोध - "emitter.setMaxListeners ()" कैसे करें?


1
v0.6.11 ... मैंने सब कुछ किया, लेकिन चेतावनी अभी भी है। :(
रिज

5
मैं उपयोग कर रहा हूँprocess.on('uncaughtException', callback);
रिज़

9
process.setMaxListeners(0); // OMG, its so simple... :D
रिज

11
मैं अधिकतम श्रोता सीमा को नहीं हटाऊंगा। आपको चेतावनी नहीं मिलेगी, लेकिन आपको मेमोरी लीक हो जाएगी।

15
इस उत्तर को इन सभी वोटों को कैसे प्राप्त किया गया, और सही उत्तर के रूप में चुना गया था? भले ही यह काम करना चाहिए, लेकिन यह पूरी तरह से गलत है !!
प्रोलिगीक

203

मैं यहां बताना चाहता हूं कि यह चेतावनी एक कारण के लिए है और एक अच्छा मौका है कि सही फिक्स सीमा नहीं बढ़ा रहा है लेकिन यह पता लगा रहा है कि आप एक ही घटना में इतने सारे श्रोताओं को क्यों जोड़ रहे हैं। केवल सीमा बढ़ाएँ यदि आप जानते हैं कि इतने सारे श्रोताओं को क्यों जोड़ा जा रहा है और विश्वास है कि यह वही है जो आप वास्तव में चाहते हैं।

मुझे यह पृष्ठ इसलिए मिला क्योंकि मुझे यह चेतावनी मिली थी और मेरे मामले में कुछ कोड में एक बग था जो मैं उपयोग कर रहा था जो कि ग्लोबल ऑब्जेक्ट को EventEmitter में बदल रहा था! मैं निश्चित रूप से विश्व स्तर पर सीमा बढ़ाने के खिलाफ सलाह दूंगा क्योंकि आप नहीं चाहते कि ये चीजें किसी का ध्यान न जाए।


14
+1। माना। चेतावनी संभावित रिसाव स्थिति को इंगित करती है और अधिकतम रूप से बढ़ते हुए अधिकतम लाइटर अनिवार्य रूप से समस्या को ठीक नहीं करेगा। jongleberry.com/understanding-possible-eventemitter-leaks.html
यिर्मयाह एडम्स

3
आप डिबग कैसे कर सकते हैं "चेतावनी: संभावित EventEmitter स्मृति रिसाव का पता चला। 11 त्रुटि श्रोताओं को जोड़ा। emitter.setMaxListeners का उपयोग करें () सीमा बढ़ाने के लिए"। हमें क्या देखना चाहिए?
फिल

2
लेकिन उस त्रुटि संदेश के साथ कहीं भी कोई स्टैक ट्रेस और कोई कोड नहीं है। मुझे "चेतावनी" और "संभव" पर पूंजी डब्ल्यू और पी मिलती है, इसलिए मुझे लगता है कि यह एक अलग त्रुटि हो सकती है। मुझे एक से अधिक घटनाओं की आवश्यकता थी, लेकिन मैंने कभी भी फोन किया। एक बार सभी मामलों में, इसलिए यह निश्चित नहीं है कि समस्या क्या है।
फिल

2
@ Phil_1984_ क्या आपको कोई समाधान मिला है? यदि ऐसा नहीं लगता है - stackoverflow.com/questions/38482223/…
Yoni Jah

3
FYI करें, पहली टिप्पणी का लिंक (jongleberry.com) ऑफ़लाइन है। यहाँ संग्रहीत संस्करण है: web.archive.org/web/20180315203155/http://www.jongleberry.com/…
जेफ़ वार्ड

76

डिफ़ॉल्ट रूप से, किसी एक घटना के लिए अधिकतम 10 श्रोता पंजीकृत किए जा सकते हैं।

यदि यह आपका कोड है, तो आप इसके माध्यम से अधिकतम सूची निर्दिष्ट कर सकते हैं:

const emitter = new EventEmitter()
emitter.setMaxListeners(100)
// or 0 to turn off the limit
emitter.setMaxListeners(0)

लेकिन अगर यह आपका कोड नहीं है, तो आप विश्व स्तर पर डिफ़ॉल्ट सीमा बढ़ाने के लिए चाल का उपयोग कर सकते हैं:

require('events').EventEmitter.prototype._maxListeners = 100;

बेशक आप सीमा को बंद कर सकते हैं लेकिन सावधान रहें:

// turn off limits by default (BE CAREFUL)
require('events').EventEmitter.prototype._maxListeners = 0;

Btw। कोड एप्लिकेशन की शुरुआत में होना चाहिए।

जोड़ें: 0.11 नोड के बाद से यह कोड डिफ़ॉल्ट सीमा को बदलने के लिए भी काम करता है:

require('events').EventEmitter.defaultMaxListeners = 0

5
यह एकमात्र समाधान था जो मेरे लिए नोड 5.6.0 में काम करता था। अनेक अनेक धन्यवाद!
एंड्रयू फॉल्कनर

मैं प्रतिक्रिया-मूल, नोड संस्करण 8 का उपयोग कर रहा हूं। *। *। यह मेरे लिए काम नहीं किया।
थॉमस वाल्डेज़

खान की आवश्यकता थी ('घटनाओं')। EventEmitter.defaultMaxListeners = इन्फिनिटी;
कार्ल एंथोनी बालुयोट

72

स्वीकृत उत्तर सीमा को बढ़ाने के बारे में शब्दार्थ प्रदान करता है, लेकिन @voltrevo ने बताया कि चेतावनी एक कारण के लिए है और आपके कोड में शायद एक बग है।

निम्नलिखित छोटी गाड़ी कोड पर विचार करें:

//Assume Logger is a module that emits errors
var Logger = require('./Logger.js');

for (var i = 0; i < 11; i++) {
    //BUG: This will cause the warning
    //As the event listener is added in a loop
    Logger.on('error', function (err) {
        console.log('error writing log: ' + err)
    });

    Logger.writeLog('Hello');
}

अब श्रोता को जोड़ने का सही तरीका देखें:

//Good: event listener is not in a loop
Logger.on('error', function (err) {
    console.log('error writing log: ' + err)
});

for (var i = 0; i < 11; i++) {
    Logger.writeLog('Hello');
}

अधिकतम सूची बदलने से पहले अपने कोड में इसी तरह के मुद्दों को खोजें (जो अन्य उत्तरों में समझाया गया है)


13
इस उत्तर को स्वीकार किया जाना चाहिए क्योंकि यह चेतावनी के पीछे वास्तविक कारण दिखाता है और इसे हल करने के लिए कैसे, +1
गणेश करेवड

यह सही जवाब है! मैं ईमानदारी से सोचता हूं कि अधिक से अधिक बग्गी कोड की वजह से मैक्सलिंटर चेतावनी ज्यादातर दिखाई देती है। मेरे मामले में यह mysql कोड था। मैं इसके लिए स्पष्टता देने के लिए उत्तर देने का प्रयास करूंगा।
एड्रियन

25

बदलें .on()के साथ once()। का उपयोग करते हुएonce() हटा घटना श्रोताओं जब घटना एक ही समारोह द्वारा नियंत्रित किया जाता।

यदि यह इसे ठीक नहीं करता है, तो अपने पैकेज में इसके साथ रेस्टोरर को फिर से इंस्टॉल करें। "restler": "git: //github.com/danwrong/restler.git#9d455ff14c57ddbe263dbbcd0289d76413bfe07d"

यह नोड के साथ restler 0.10 दुर्व्यवहार के साथ करना है। आप यहाँ git पर बंद मुद्दे को देख सकते हैं: https://github.com/danwrong/restler/issues/112 हालाँकि, npm को अभी तक इसे अपडेट नहीं करना है, इसीलिए आपको git head को संदर्भित करना होगा।


इस कठपुतली ढांचे का उपयोग कर मेरे कोड पर इस त्रुटि को ठीक करें
C Alonso C Ortega

5

मुझे यह चेतावनी तब मिल रही है जब मैं अपने मैक ओएसएक्स पर एग्लियो स्थापित करता हूं।

मैं इसे ठीक करने के लिए cmd का उपयोग करता हूं।

sudo npm install -g npm@next

https://github.com/npm/npm/issues/13806


4

नोड संस्करण: v11.10.1

स्टैक ट्रेस से चेतावनी संदेश:

process.on('warning', e => console.warn(e.stack));
(node:17905) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit
    at _addListener (events.js:255:17)
    at Connection.addListener (events.js:271:10)
    at Connection.Readable.on (_stream_readable.js:826:35)
    at Connection.once (events.js:300:8)
    at Connection._send (/var/www/html/fleet-node-api/node_modules/http2/lib/protocol/connection.js:355:10)
    at processImmediate (timers.js:637:19)
    at process.topLevelDomainCallback (domain.js:126:23)

गितुब मुद्दों, प्रलेखन और इसी तरह की घटना एमिटर मेमोरी लीक बनाने के लिए खोज करने के बाद, इस मुद्दे को आईओएस पुश अधिसूचना के लिए उपयोग किए गए नोड-एप मॉड्यूल के कारण देखा गया था ।

इसने इसे हल किया:

आपके पास प्रत्येक प्रमाणपत्र / कुंजी जोड़ी के लिए केवल एक प्रदाता प्रति-प्रक्रिया बनानी चाहिए। आपको प्रत्येक सूचना के लिए एक नया प्रदाता बनाने की आवश्यकता नहीं है। यदि आप केवल एक ऐप पर सूचनाएं भेज रहे हैं तो एक से अधिक प्रदाता की आवश्यकता नहीं है।

यदि आप अपने ऐप में लगातार प्रदाता इंस्टेंसेस बना रहे हैं, तो सुनिश्चित करें कि जब आप अपने प्रोवाइडरों और मेमोरी को जारी करने के लिए प्रोवाइडर के साथ प्रदाता (शटडाउन) कॉल करें।

जब भी अधिसूचना भेजी गई थी, तो मैं प्रदाता वस्तु बना रहा था और उम्मीद थी कि इसे साफ़ करने के लिए जीसी।


2

मेरे मामले में, यह child.stderr.pipe(process.stderr)तब कहा जा रहा था जब मैं बच्चे के 10 (या तो) उदाहरणों की शुरुआत कर रहा था। तो कुछ भी, जो एक घटना हैंडलर को उसी ईवेंट में उसी ईवेंट को संलग्न करने की ओर ले जाता है, जो इस त्रुटि को फेंकने के लिए नोडज का कारण बनता है।


2

कभी-कभी ये चेतावनी तब होती है जब यह ऐसा कुछ नहीं है जो हमने किया है, लेकिन कुछ ऐसा है जिसे हम करना भूल गए हैं!

जब मैंने npm के साथ dotenv पैकेज स्थापित किया था, तो मुझे इस चेतावनी का सामना करना पड़ा, लेकिन इससे पहले कि मैं अपने ऐप की शुरुआत में आवश्यकता ('dotenv') लोड () कथन को जोड़ने के लिए इधर-उधर रुका हुआ था। जब मैं परियोजना में वापस आया, तो मुझे "संभावित ईवेंटमीटर मेमोरी लीक का पता चला" चेतावनी मिलनी शुरू हो गई।

मुझे लगता है कि समस्या कुछ मैंने की थी, कुछ ऐसा नहीं था जो मैंने नहीं किया था!

एक बार जब मैंने अपने निरीक्षण की खोज की और आवश्यकता बयान जोड़ दिया, तो स्मृति रिसाव की चेतावनी को मंजूरी दे दी गई।


2

जब भी संभव हो मैं लॉग को दबाने के बजाय समस्याओं का शिकार करना और उन्हें ठीक करना पसंद करता हूं। अपने ऐप में इस मुद्दे को देखने के कुछ दिनों के बाद, मुझे एहसास हुआ कि मैं req.socketसॉकेट io त्रुटियों को पकड़ने के लिए एक एक्सप्रेस मिडलवेयर पर श्रोताओं को स्थापित कर रहा था जो कि पॉपिंग बनाए रखते थे। कुछ बिंदु पर, मैंने सीखा कि यह आवश्यक नहीं था, लेकिन मैंने श्रोताओं को वैसे भी रखा। मैंने उन्हें हटा दिया और आपको जो त्रुटि हो रही है, वह दूर हो गई। मैंने सत्यापित किया कि निम्नलिखित मिडलवेयर के साथ और उसके बिना मेरे सर्वर के अनुरोधों को चलाने का कारण यह था:

socketEventsHandler(req, res, next) {
        req.socket.on("error", function(err) {
            console.error('------REQ ERROR')
            console.error(err.stack)
        });
        res.socket.on("error", function(err) {
            console.error('------RES ERROR')
            console.error(err.stack)
        });
        next();
    }

उस मिडलवेयर को हटाने से आपको दिखाई दे रही चेतावनी बंद हो गई। मैं आपके कोड के चारों ओर देखूंगा और कहीं भी खोजने की कोशिश करूंगा कि आप श्रोताओं को स्थापित कर सकते हैं जिनकी आपको आवश्यकता नहीं है।


1

मुझे भी यही समस्या आ रही थी। और समस्या इसलिए हुई क्योंकि मैं 8080 को सुन रहा था, 2 श्रोताओं पर।

setMaxListeners() ठीक काम करता है, लेकिन मैं इसकी सिफारिश नहीं करूंगा।

सही तरीका यह है कि, अतिरिक्त श्रोताओं के लिए अपने कोड की जाँच करें, श्रोता को हटा दें या उस पोर्ट नंबर को बदल दें जिस पर आप सुन रहे हैं, इसने आपकी समस्या को ठीक कर दिया है।


1

मैं आज तक यह कर रहा था जब मैं शुरू करता हूं grunt watch। अंत में हल किया

watch: {
  options: {
    maxListeners: 99,
    livereload: true
  },
}

कष्टप्रद संदेश चला गया है।


1

उपयोग करने वाले नए बनाने से पहले आपको सभी श्रोताओं को साफ़ करना होगा:

क्लाइंट सर्वर

socket.removeAllListeners(); 

सॉकेट मान लेना आपके क्लाइंट सॉकेट / या बनाया सर्वर सॉकेट है।

उदाहरण के लिए connectश्रोता को इस तरह हटाने के लिए आप विशिष्ट ईवेंट श्रोताओं से भी सदस्यता ले सकते हैं :

this.socket.removeAllListeners("connect");

0

आपने कहा कि आप process.on('uncaughtException', callback);
इस कथन का उपयोग कहां कर रहे हैं? क्या यह कॉलबैक के भीतर है http.createServer?
यदि हाँ, तो एक ही कॉलबैक की अलग-अलग प्रति प्रत्येक नए अनुरोध पर अनक्रेडिसेप्शन ईवेंट से जुड़ी हुई हो जाएगी , क्योंकि function (req, res) { ... }हर बार नया अनुरोध निष्पादित हो जाता है और इसलिए यह कथन process.on('uncaughtException', callback);
नोट करेगा कि प्रक्रिया ऑब्जेक्ट आपके सभी अनुरोधों और श्रोताओं को जोड़ने के लिए वैश्विक है इसके आयोजन के लिए हर बार एक नया अनुरोध आने से कोई मतलब नहीं होगा। आप इस तरह का व्यवहार नहीं चाहते होंगे।
यदि आप प्रत्येक नए अनुरोध के लिए एक नया श्रोता संलग्न करना चाहते हैं, तो आपको घटना से जुड़े सभी पिछले श्रोताओं को हटा देना चाहिए क्योंकि अब उन्हें उपयोग करने की आवश्यकता नहीं होगी:
process.removeAllListeners('uncaughtException');


0

इसके लिए हमारी टीम का फिक्स हमारे .npmrc से एक रजिस्ट्री रास्ता निकाल रहा था। आरसी फ़ाइल में हमारे पास दो पथ उपनाम थे, और एक आर्टिफैक्टिक उदाहरण की ओर इशारा कर रहा था जिसे हटा दिया गया था।

त्रुटि का हमारे ऐप के वास्तविक कोड से कोई लेना-देना नहीं था, बल्कि हमारे विकास के वातावरण के साथ सब कुछ करना था।


0

मैं एक ही मुद्दे का सामना कर रहा था, लेकिन मैं सफलतापूर्वक async प्रतीक्षा के साथ संभाला है।
कृपया जाँच करें कि क्या यह मदद करता है।

आज्ञा देना dataLength = 25;
से पहले: के
  लिए (मैं i = 0; मैं <dataLength; मैं ++) {
      sftp.get (RemotePath, fs.createWriteStream ( xyzProject/${data[i].name}));
  } के

बाद: के
  लिए (मैं i = 0; मैं <dataLength; मैं ++) {
      प्रतीक्षा sftp.get (RemotePath, fs.createWriteStream ( xyzProject/${data[i].name}));
  }


0

चेतावनी के वास्तविक समस्या / मूल कारण को हल करने के लिए मुझे एक विचार देने के लिए RLaaa का धन्यवाद । खैर मेरे मामले में यह MySQL छोटी गाड़ी कोड था।

आपको इस तरह कोड के साथ एक वादा लिखा प्रदान करना:

pool.getConnection((err, conn) => {

  if(err) reject(err)

  const q = 'SELECT * from `a_table`'

  conn.query(q, [], (err, rows) => {

    conn.release()

    if(err) reject(err)

    // do something
  })

  conn.on('error', (err) => {

     reject(err)
  })
})

सूचना conn.on('error')कोड में एक श्रोता है। यह कोड शाब्दिक रूप से श्रोता को बार-बार जोड़ने पर निर्भर करता है कि आप क्वेरी को कितनी बार कहते हैं। इस बीच if(err) reject(err)वही काम करता है।

तो मैंने conn.on('error')श्रोता और वोइला को हटा दिया ... हल! आशा है कि यह आपकी मदद करता है।


-4

इसे अपने server.js (या जो भी आपका मुख्य Node.js ऐप शामिल है) की पहली पंक्ति में रखें:

require('events').EventEmitter.prototype._maxListeners = 0;

और त्रुटि दूर हो जाती है :)


आपने मुझे एक मुख्य फाइल में डालने का विचार दिया, और इसने काम किया। मैं बस गलत जगह पर डाल रहा था। धन्यवाद!
sklimkovitch
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.