Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
};
// If the server "crashed" with a normal exit code indicating that it was stopped successfully
// don't force it to reboot. This can happen if a plugin stops the server for someone.
if (!Config.get('internals.clean_exit_is_crash', true) && parseInt(props.ExitCode, 10) === 0 && !props.OOMKilled) {
return;
}
// If crash detection is disabled for the server don't do anything.
if (!_.get(this.json, 'container.crashDetection', true)) {
this.log.warn(props, 'Server detected as entering a crashed state; crash handler is disabled; aborting reboot.');
return;
}
this.emit('console', `${Ansi.style['bg-red']}${Ansi.style.white}[Pterodactyl Daemon] ---------- Detected server process in a crashed state! ----------`);
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] Exit Code: ${Ansi.style.reset}${props.ExitCode}`);
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] Out of Memory: ${Ansi.style.reset}${props.OOMKilled}`);
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] Error Response: ${Ansi.style.reset}${props.Error}`);
this.emit('crashed');
if (moment.isMoment(this.lastCrash) && moment(this.lastCrash).add(60, 'seconds').isAfter(moment())) {
this.setCrashTime();
this.log.warn(props, 'Server detected as crashed but has crashed within the last 60 seconds; aborting reboot.');
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] Aborting automatic reboot due to crash within the last 60 seconds.`);
return;
}
this.log.warn(props, 'Server detected as crashed! Attempting server reboot.');
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] Server process detected as entering a crashed state; rebooting.`);
this.setCrashTime();
this.stream.on('data', data => {
if (!throttleEnabled || throttleTriggered) {
return;
}
const lines = _.split(data, /\r?\n/);
linesSent += (lines.length - 1);
// If we've suddenly gone over the trigger threshold send a message to the console and register
// that event. The trigger will be reset automatically by the check interval time.
if (linesSent > maxLinesPerInterval) {
throttleTriggered = true;
throttleTriggerCount += 1;
this.server.log.debug({ throttleTriggerCount }, 'Server has passed the throttle detection threshold. Penalizing server process.');
this.server.output(`${Ansi.style.yellow}[Pterodactyl Daemon] Your server is sending too much data too quickly! Automatic spam detection triggered.`);
}
// We've triggered it too many times now, kill the server because clearly something is not
// working correctly.
if (throttleTriggerCount > maximumThrottleTriggers) {
this.server.output(`${Ansi.style.red}[Pterodactyl Daemon] Your server is sending too much data, process is being killed.`);
this.server.log.warn('Server has triggered automatic kill due to excessive data output. Potential DoS attack.');
this.server.kill(() => {}); // eslint-disable-line
}
}).on('end', () => {
this.stream = undefined;
},
callback => {
this.log.info('Completed rebuild process for server container.');
this.emit('console', `${Ansi.style.green}[Pterodactyl Daemon] Completed rebuild process for server. Server is now booting.`);
this.start(callback);
},
], err => {
if (err) {
this.setStatus(Status.OFF);
this.emit('console', `${Ansi.style.red}[Pterodactyl Daemon] A fatal error was encountered booting this container.`);
this.buildInProgress = false;
this.log.error(err);
}
});
} else {
this.emit('console', `${Ansi.style.cyan}[Pterodactyl Daemon] Please wait while your server is being rebuilt.`);
}
return next(new Error('Server is currently queued for a container rebuild. Your request has been accepted and will be processed once the rebuild is complete.'));
}
Async.series([
callback => {
this.log.debug('Checking size of server folder before booting.');
this.emit('console', `${Ansi.style.yellow}[Pterodactyl Daemon] Checking size of server data directory...`);
this.fs.size((err, size) => {
if (err) return callback(err);
// 10 MB overhead accounting.
const sizeInMb = Math.round(size / (1000 * 1000));
this.currentDiskUsed = sizeInMb;
if (this.json.build.disk > 0 && sizeInMb > this.json.build.disk) {
linesSent += (lines.length - 1);
// If we've suddenly gone over the trigger threshold send a message to the console and register
// that event. The trigger will be reset automatically by the check interval time.
if (linesSent > maxLinesPerInterval) {
throttleTriggered = true;
throttleTriggerCount += 1;
this.server.log.debug({ throttleTriggerCount }, 'Server has passed the throttle detection threshold. Penalizing server process.');
this.server.output(`${Ansi.style.yellow}[Pterodactyl Daemon] Your server is sending too much data too quickly! Automatic spam detection triggered.`);
}
// We've triggered it too many times now, kill the server because clearly something is not
// working correctly.
if (throttleTriggerCount > maximumThrottleTriggers) {
this.server.output(`${Ansi.style.red}[Pterodactyl Daemon] Your server is sending too much data, process is being killed.`);
this.server.log.warn('Server has triggered automatic kill due to excessive data output. Potential DoS attack.');
this.server.kill(() => {}); // eslint-disable-line
}
}).on('end', () => {
this.stream = undefined;
this.service.onPreflight().then(next).catch(err => {
if (err instanceof Errors.FileParseError) {
this.emit('console', `${Ansi.style.yellow}[Pterodactyl Daemon] Encountered an error while processing ${err.file} -- this could lead to issues running the server.`);
this.emit('console', `${Ansi.style.yellow}[Pterodactyl Daemon] ${err.message}`);
return next();
}
if (err instanceof Errors.NoEggConfigurationError) {
this.emit('console', `${Ansi.style['bg-red']}${Ansi.style.white}[Pterodactyl Daemon] No server egg configuration could be located; aborting startup.`);
}
return next(err);
});
}
this.processData.process = {};
}
}
switch (status) {
case Status.OFF:
this.emit('console', `${Ansi.style.cyan}[Pterodactyl Daemon] Server marked as ${Ansi.style.bold}OFF`);
break;
case Status.ON:
this.emit('console', `${Ansi.style.cyan}[Pterodactyl Daemon] Server marked as ${Ansi.style.bold}ON`);
break;
case Status.STARTING:
this.emit('console', `${Ansi.style.cyan}[Pterodactyl Daemon] Server marked as ${Ansi.style.bold}STARTING`);
break;
case Status.STOPPING:
this.emit('console', `${Ansi.style.cyan}[Pterodactyl Daemon] Server marked as ${Ansi.style.bold}STOPPING`);
break;
default:
break;
}
this.log.info(`Server status has been changed to ${inverted[status]}`);
this.status = status;
this.emit(`is:${inverted[status]}`);
this.emit('status', status);
}
}).catch(readError => {
activeSocket.emit('console', {
line: `${Ansi.style.red}[Pterodactyl Daemon] An error was encountered while attempting to read the log file!`,
});
return this.server.log.error(readError);
});
});
this.docker.kill(err => {
this.setStatus(Status.OFF);
this.emit('console', `${Ansi.style['bg-red']}${Ansi.style.white}[Pterodactyl Daemon] Server marked as ${Ansi.style.bold}KILLED.`);
return next(err);
});
}
callback => {
this.log.debug('Initializing for boot sequence, running preflight checks.');
this.emit('console', `${Ansi.style.green}[Pterodactyl Daemon] Running server preflight.`);
this.preflight(callback);
},
callback => {