Search code examples
javascriptnode.jssocket.iochild-processmplayer

How can i stop a child process by its reference variable in node.js on Debian?


I have a Node.js server set up and i am trying to stop a process which are started when some conditions are met.

Here is my server script:

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var fs = require('fs');

var sys = require('sys')
var exec = require('child_process').exec;
var child;

var musicDirectory = __dirname + '/music/';
var musicFiles = [];
fetchMusic();

server.listen(80);

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/views/index.html');
});


io.on('connection', function (socket) {
    console.log("We have a new visitor.");
    socket.emit('music', {files: musicFiles} );
    socket.on('File to play', function (fileToPlay) {
        exec("ls " + musicDirectory, function (error, stdout, stderr) {
            var filesInMusicDirectory = stdout.split("\n");

            for (var i = 0; i < filesInMusicDirectory.length; i++) {
                if (filesInMusicDirectory[i] == fileToPlay) {
                    if (typeof child !== "undefined") {
                            child.kill();
                            console.log("Killing process");
                    }
                    child = exec("mplayer " + "'" + musicDirectory + fileToPlay + "'");
                    console.log(fileToPlay + " is in directory.");
                    break;
                }
            }


            if (error !== null) {
                console.log('exec error: ' + error);
            }
        });
    });
});

function fetchMusic()
{
    fs.readdir(musicDirectory, function(err,data) {
        for (var i = 0; i < data.length; i++) {
            musicFiles.push(data[i]);
        };
    });
}

As you can se i have declared a variable named child on line 8 which i am using like this: child = exec("mplayer " + "'" + musicDirectory + fileToPlay + "'");.

Now, all i want to do, is to stop this process when some conditions are met, so i am trying to to this with child.kill().

The functionality of my little experiment works up to the point where i want to kill the child process. It does not do that, the child.kill() function seems to be failing, and probably because i have missunderstood something.

Could anyone try help me understand why this process wont end. I am reading the documentation as i am writing this, but there are a lot of things to go through.

My question is: Why does not the kill() function stop the process with my code, and what can i do to achieve what i want?

Update

Ok i have fiddled around a bit. I added tree-kill since the child.kill() functionality did not work, and tried to use it with the extracted Pid from the child process which i know is not null or undefined like this: kill = require('tree-kill') and kill(child.pid).

Now the process, or rather, the music stops when the same conditions are met but it it doesnt go thorugh with the rest, playing another song. Instead there are outputted the following in the server console:

Baby (metal cover by Leo Moracchioli).mp3 fed to mPlayer
undefined
STDOUT: MPlayer2 2.0-728-g2c378c7-4+b1 (C) 2000-2012 MPlayer Team
Cannot open file '/root/.mplayer/input.conf': No such file or directory
Failed to open /root/.mplayer/input.conf.
Cannot open file '/etc/mplayer/input.conf': No such file or directory
Failed to open /etc/mplayer/input.conf.

Playing /home/danlevi/Documents/NodeServer/music/Bad Blood (metal cover by Leo Moracchioli).mp3.
Detected file format: MP2/3 (MPEG audio layer 2/3) (libavformat)
[mp3 @ 0xb62803a0]max_analyze_duration 5000000 reached
[lavf] stream 0: audio (mp3), -aid 0
Clip info:
 major_brand: dash
 minor_version: 0
 compatible_brands: iso6mp41
 creation_time: 2015-09-29 08:04:29
 encoder: Lavf54.20.4
Load subtitles in /home/danlevi/Documents/NodeServer/music/
Selected audio codec: MPEG 1.0/2.0/2.5 layers I, II, III [mpg123]
AUDIO: 44100 Hz, 2 ch, s16le, 128.0 kbit/9.07% (ratio: 16000->176400)
AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
Video: no video
Starting playback...


MPlayer interrupted by signal 15 in module: unknown

Exiting... (Quit)

A:   9.1 (09.0) of 281.8 (04:41.7)  0.2% 

A:   9.1 (09.0) of 281.8 (04:41.7)  0.2% 

So i think i have made som progress in the right direction, now i know that i have the correct process, and mPlayer is indeed interrupted, but the new song does not play.


Solution

  • The reason why this dont work is because the correct kill signal is not sent.

    The SIGTERM signal which is the default signal is a generic signal used to cause program termination. Unlike SIGQUIT, this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate.

    Since the application should kill the process immediately we use SIGQUIT.

    It is also important to adjust the timeout and buffer for the child process so that it finishes.