Compare commits

..

2 Commits

Author SHA1 Message Date
Johannes Zellner e53aaddc9c Add 3.3.3 changes 2018-11-13 12:54:40 +01:00
Johannes Zellner d3ebb99131 Fix apptask concurrency
This broke due to async behavior introduced with 1dc649b7a2
2018-11-13 12:54:40 +01:00
2 changed files with 43 additions and 29 deletions
+13
View File
@@ -1438,3 +1438,16 @@
* Add support for hyphenated subdomains
* Add domain, mail events to eventlog
[3.3.3]
* Use new addons with REST APIs
* Ubuntu 18.04 LTS support
* Custom env vars can be set per application
* Add a button to renew certs
* Add better support for private builds
* cloudflare: Fix crash when using bad email
* cloudflare: HTTP proxying works now
* add new exoscale-sos regions
* Add UI to toggle dynamic DNS
* Add support for hyphenated subdomains
* Add domain, mail events to eventlog
+30 -29
View File
@@ -98,6 +98,7 @@ function startNextTask() {
startAppTask(gPendingTasks.shift(), NOOP_CALLBACK);
}
// WARNING callback has to be called in sync for the concurrency check to work!
function startAppTask(appId, callback) {
assert.strictEqual(typeof appId, 'string');
assert.strictEqual(typeof callback, 'function');
@@ -126,39 +127,39 @@ function startAppTask(appId, callback) {
return callback();
}
// ensure log folder
mkdirp.sync(path.join(paths.LOG_DIR, appId));
var logFilePath = path.join(paths.LOG_DIR, appId, 'apptask.log');
var fd;
// will autoclose
fs.open(logFilePath, 'a', function (error, fd) {
if (error) {
debug('Unable to open log file, queueing task for %s', appId, error);
gPendingTasks.push(appId);
return callback();
// have to use sync here to avoid async callback, breaking concurrency check
try {
mkdirp.sync(path.join(paths.LOG_DIR, appId)); // ensure log folder
fd = fs.openSync(logFilePath, 'a'); // will autoclose
} catch (e) {
debug('Unable to get log filedescriptor, queueing task for %s', appId, e);
gPendingTasks.push(appId);
return callback();
}
// when parent process dies, apptask processes are killed because KillMode=control-group in systemd unit file
gActiveTasks[appId] = child_process.fork(__dirname + '/apptask.js', [ appId ], { stdio: [ 'pipe', fd, fd, 'ipc' ]});
var pid = gActiveTasks[appId].pid;
debug('Started task of %s pid: %s. See logs at %s', appId, pid, logFilePath);
gActiveTasks[appId].once('exit', function (code, signal) {
debug('Task for %s pid %s completed with status %s', appId, pid, code);
if (code === null /* signal */ || (code !== 0 && code !== 50)) { // apptask crashed
debug('Apptask crashed with code %s and signal %s', code, signal);
sendFailureLogs('apptask', { unit: 'box' });
appdb.update(appId, { installationState: appdb.ISTATE_ERROR, installationProgress: 'Apptask crashed with code ' + code + ' and signal ' + signal }, NOOP_CALLBACK);
} else if (code === 50) {
sendFailureLogs('apptask', { unit: 'box' });
}
// when parent process dies, apptask processes are killed because KillMode=control-group in systemd unit file
gActiveTasks[appId] = child_process.fork(__dirname + '/apptask.js', [ appId ], { stdio: [ 'pipe', fd, fd, 'ipc' ]});
var pid = gActiveTasks[appId].pid;
debug('Started task of %s pid: %s. See logs at %s', appId, pid, logFilePath);
gActiveTasks[appId].once('exit', function (code, signal) {
debug('Task for %s pid %s completed with status %s', appId, pid, code);
if (code === null /* signal */ || (code !== 0 && code !== 50)) { // apptask crashed
debug('Apptask crashed with code %s and signal %s', code, signal);
sendFailureLogs('apptask', { unit: 'box' });
appdb.update(appId, { installationState: appdb.ISTATE_ERROR, installationProgress: 'Apptask crashed with code ' + code + ' and signal ' + signal }, NOOP_CALLBACK);
} else if (code === 50) {
sendFailureLogs('apptask', { unit: 'box' });
}
delete gActiveTasks[appId];
locker.unlock(locker.OP_APPTASK); // unlock event will trigger next task
});
callback();
delete gActiveTasks[appId];
locker.unlock(locker.OP_APPTASK); // unlock event will trigger next task
});
callback();
}
function stopAppTask(appId, callback) {