Projekt

Obecné

Profil

Stáhnout (4.03 KB) Statistiky
| Větev: | Revize:
1
// Note: since nyc uses this module to output coverage, any lines
2
// that are in the direct sync flow of nyc's outputCoverage are
3
// ignored, since we can never get coverage for them.
4
var assert = require('assert')
5
var signals = require('./signals.js')
6
var isWin = /^win/i.test(process.platform)
7

    
8
var EE = require('events')
9
/* istanbul ignore if */
10
if (typeof EE !== 'function') {
11
  EE = EE.EventEmitter
12
}
13

    
14
var emitter
15
if (process.__signal_exit_emitter__) {
16
  emitter = process.__signal_exit_emitter__
17
} else {
18
  emitter = process.__signal_exit_emitter__ = new EE()
19
  emitter.count = 0
20
  emitter.emitted = {}
21
}
22

    
23
// Because this emitter is a global, we have to check to see if a
24
// previous version of this library failed to enable infinite listeners.
25
// I know what you're about to say.  But literally everything about
26
// signal-exit is a compromise with evil.  Get used to it.
27
if (!emitter.infinite) {
28
  emitter.setMaxListeners(Infinity)
29
  emitter.infinite = true
30
}
31

    
32
module.exports = function (cb, opts) {
33
  assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler')
34

    
35
  if (loaded === false) {
36
    load()
37
  }
38

    
39
  var ev = 'exit'
40
  if (opts && opts.alwaysLast) {
41
    ev = 'afterexit'
42
  }
43

    
44
  var remove = function () {
45
    emitter.removeListener(ev, cb)
46
    if (emitter.listeners('exit').length === 0 &&
47
        emitter.listeners('afterexit').length === 0) {
48
      unload()
49
    }
50
  }
51
  emitter.on(ev, cb)
52

    
53
  return remove
54
}
55

    
56
module.exports.unload = unload
57
function unload () {
58
  if (!loaded) {
59
    return
60
  }
61
  loaded = false
62

    
63
  signals.forEach(function (sig) {
64
    try {
65
      process.removeListener(sig, sigListeners[sig])
66
    } catch (er) {}
67
  })
68
  process.emit = originalProcessEmit
69
  process.reallyExit = originalProcessReallyExit
70
  emitter.count -= 1
71
}
72

    
73
function emit (event, code, signal) {
74
  if (emitter.emitted[event]) {
75
    return
76
  }
77
  emitter.emitted[event] = true
78
  emitter.emit(event, code, signal)
79
}
80

    
81
// { <signal>: <listener fn>, ... }
82
var sigListeners = {}
83
signals.forEach(function (sig) {
84
  sigListeners[sig] = function listener () {
85
    // If there are no other listeners, an exit is coming!
86
    // Simplest way: remove us and then re-send the signal.
87
    // We know that this will kill the process, so we can
88
    // safely emit now.
89
    var listeners = process.listeners(sig)
90
    if (listeners.length === emitter.count) {
91
      unload()
92
      emit('exit', null, sig)
93
      /* istanbul ignore next */
94
      emit('afterexit', null, sig)
95
      /* istanbul ignore next */
96
      if (isWin && sig === 'SIGHUP') {
97
        // "SIGHUP" throws an `ENOSYS` error on Windows,
98
        // so use a supported signal instead
99
        sig = 'SIGINT'
100
      }
101
      process.kill(process.pid, sig)
102
    }
103
  }
104
})
105

    
106
module.exports.signals = function () {
107
  return signals
108
}
109

    
110
module.exports.load = load
111

    
112
var loaded = false
113

    
114
function load () {
115
  if (loaded) {
116
    return
117
  }
118
  loaded = true
119

    
120
  // This is the number of onSignalExit's that are in play.
121
  // It's important so that we can count the correct number of
122
  // listeners on signals, and don't wait for the other one to
123
  // handle it instead of us.
124
  emitter.count += 1
125

    
126
  signals = signals.filter(function (sig) {
127
    try {
128
      process.on(sig, sigListeners[sig])
129
      return true
130
    } catch (er) {
131
      return false
132
    }
133
  })
134

    
135
  process.emit = processEmit
136
  process.reallyExit = processReallyExit
137
}
138

    
139
var originalProcessReallyExit = process.reallyExit
140
function processReallyExit (code) {
141
  process.exitCode = code || 0
142
  emit('exit', process.exitCode, null)
143
  /* istanbul ignore next */
144
  emit('afterexit', process.exitCode, null)
145
  /* istanbul ignore next */
146
  originalProcessReallyExit.call(process, process.exitCode)
147
}
148

    
149
var originalProcessEmit = process.emit
150
function processEmit (ev, arg) {
151
  if (ev === 'exit') {
152
    if (arg !== undefined) {
153
      process.exitCode = arg
154
    }
155
    var ret = originalProcessEmit.apply(this, arguments)
156
    emit('exit', process.exitCode, null)
157
    /* istanbul ignore next */
158
    emit('afterexit', process.exitCode, null)
159
    return ret
160
  } else {
161
    return originalProcessEmit.apply(this, arguments)
162
  }
163
}
(3-3/5)