-
Couldn't load subscription status.
- Fork 14
Replace synchronous file operations with async versions #42
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -124,11 +124,21 @@ export default class Container { | |
| private saveCodeFiles = (code: string, includeFileData: Buffer | null): void => { | ||
| // Create data directory and save code from request | ||
| console.log(`${this.logPrefix}Saving code to ${this.codeHostPath}`); | ||
| if (!fs.existsSync(this.dataHostPath)) fs.mkdirSync(this.dataHostPath); | ||
| fs.writeFileSync(this.codeHostPath, code); | ||
| fs.access(this.dataHostPath, fs.constants.F_OK, (errPathExists) => { | ||
| if (errPathExists) { | ||
| fs.mkdir(this.dataHostPath, (err) => { if (err) throw err; }); | ||
| } | ||
| }); | ||
| fs.writeFile(this.codeHostPath, code, (err) => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way that Javascript does concurrency can be super confusing at first. We want to do this sequentially:
It might look like this code does that, but actually it does this:
If we could only use callbacks, we would need to put all code following We should be able to do something like this: The You'll also need to convert Now that It looks like it gets called from the Container constructor. Unfortunately constructors cannot be async functions (Javascript requires that objects are constructed synchronously), so you won't be able to use Or, since I think we're starting to get several async-y things that we need to do in the constructor, we could define an async function inside of the constructor and invoke that: |
||
| if (err) throw err; | ||
| console.log(`${this.logPrefix}Saved file to ${this.codeHostPath}`); | ||
| }); | ||
| if (includeFileData) { | ||
| console.log(`${this.logPrefix}Writing include file to ${this.includeFileHostPath}`); | ||
| fs.writeFileSync(this.includeFileHostPath, includeFileData); | ||
| fs.writeFile(this.includeFileHostPath, includeFileData, (err) => { | ||
| if (err) throw err; | ||
| console.log(`${this.logPrefix}Saved file to ${this.includeFileHostPath}`); | ||
| }); | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -315,8 +325,12 @@ export default class Container { | |
| // Remove uploaded file. We don't care about errors, in case the file | ||
| // was already removed (or was never successfully created to begin | ||
| // with) | ||
| try { fs.unlinkSync(this.codeHostPath); } catch { /* ignore */ } | ||
| try { fs.unlinkSync(this.includeFileHostPath); } catch { /* ignore */ } | ||
| fs.unlink(this.codeHostPath, () => { | ||
| console.log(`${this.logPrefix}Deleted ${this.codeHostPath}`); | ||
| }); | ||
| fs.unlink(this.includeFileHostPath, () => { | ||
| console.log(`${this.logPrefix}Deleted ${this.includeFileHostPath}`); | ||
| }); | ||
| // Shut down gdb server, if it's running | ||
| if (this.gdbMiServer) { | ||
| this.gdbMiServer.close(); | ||
|
|
@@ -481,27 +495,25 @@ export default class Container { | |
| // have started yet, and there's not much we can do | ||
| if (!this.containerId) return; | ||
|
|
||
| let cpuUsageNs; | ||
| try { | ||
| // TODO: get rid of synchronous read | ||
| cpuUsageNs = parseInt( | ||
| fs.readFileSync( | ||
| `/sys/fs/cgroup/cpu/docker/${this.containerId}/cpuacct.usage`, | ||
| ).toString(), | ||
| 10, | ||
| ); | ||
| } catch (exc) { | ||
| console.warn(`${this.logPrefix}Error loading cgroup CPU usage!`, exc); | ||
| return; | ||
| } | ||
| const cpuUsageMs = cpuUsageNs / 1000000; | ||
| console.debug(`${this.logPrefix}Current CPU time used: ${cpuUsageMs}ms`); | ||
| if (cpuUsageMs > MAX_CPU_TIME) { | ||
| console.warn(`${this.logPrefix}Container ${this.containerName} exceeded its CPU ` | ||
| + 'quota! Killing container'); | ||
| childProcess.execFile('docker', ['kill', this.containerName]); | ||
| this.showErrorBanner('The program exceeded its CPU quota.'); | ||
| } | ||
| fs.readFile( | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comments here about using async/await with promises instead of callbacks |
||
| `/sys/fs/cgroup/cpu/docker/${this.containerId}/cpuacct.usage`, | ||
| (err, data) => { | ||
| if (err) { | ||
| console.warn(`${this.logPrefix}Error loading cgroup CPU usage!`, err); | ||
| return; | ||
| } | ||
|
|
||
| const cpuUsageNs = parseInt(data.toString(), 10); | ||
| const cpuUsageMs = cpuUsageNs / 1000000; | ||
| console.debug(`${this.logPrefix}Current CPU time used: ${cpuUsageMs}ms`); | ||
| if (cpuUsageMs > MAX_CPU_TIME) { | ||
| console.warn(`${this.logPrefix}Container ${this.containerName} exceeded its CPU ` | ||
| + 'quota! Killing container'); | ||
| childProcess.execFile('docker', ['kill', this.containerName]); | ||
| this.showErrorBanner('The program exceeded its CPU quota.'); | ||
| } | ||
| }, | ||
| ); | ||
| }, 1000); | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rename errPathExists to something like accessError, since the "PathExists" part could imply that the path does exist