1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-10 16:11:13 -05:00

Fixes #2033, shared queue push bug (#2158)

This commit is contained in:
Ryan Dahl 2019-04-21 12:16:55 -04:00 committed by GitHub
parent cd19da62d9
commit 961f87e1c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 3 deletions

View file

@ -1,4 +1,20 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
/*
SharedQueue Binary Layout
+-------------------------------+-------------------------------+
| NUM_RECORDS (32) |
+---------------------------------------------------------------+
| NUM_SHIFTED_OFF (32) |
+---------------------------------------------------------------+
| HEAD (32) |
+---------------------------------------------------------------+
| OFFSETS (32) |
+---------------------------------------------------------------+
| RECORD_ENDS (*MAX_RECORDS) ...
+---------------------------------------------------------------+
| RECORDS (*MAX_RECORDS) ...
+---------------------------------------------------------------+
*/
(window => {
const GLOBAL_NAMESPACE = "Deno";
@ -69,7 +85,7 @@
let off = head();
let end = off + buf.byteLength;
let index = numRecords();
if (end > shared32.byteLength) {
if (end > shared32.byteLength || index >= MAX_RECORDS) {
console.log("shared_queue.ts push fail");
return false;
}
@ -141,6 +157,7 @@
setAsyncHandler,
dispatch,
sharedQueue: {
MAX_RECORDS,
head,
numRecords,
size,

View file

@ -1,4 +1,21 @@
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
/*
SharedQueue Binary Layout
+-------------------------------+-------------------------------+
| NUM_RECORDS (32) |
+---------------------------------------------------------------+
| NUM_SHIFTED_OFF (32) |
+---------------------------------------------------------------+
| HEAD (32) |
+---------------------------------------------------------------+
| OFFSETS (32) |
+---------------------------------------------------------------+
| RECORD_ENDS (*MAX_RECORDS) ...
+---------------------------------------------------------------+
| RECORDS (*MAX_RECORDS) ...
+---------------------------------------------------------------+
*/
use crate::libdeno::deno_buf;
const MAX_RECORDS: usize = 100;
@ -36,6 +53,7 @@ impl SharedQueue {
}
fn reset(&mut self) {
debug!("rust:shared_queue:reset");
let s: &mut [u32] = self.as_u32_slice_mut();
s[INDEX_NUM_RECORDS] = 0;
s[INDEX_NUM_SHIFTED_OFF] = 0;
@ -75,6 +93,11 @@ impl SharedQueue {
s[INDEX_HEAD] as usize
}
fn num_shifted_off(&self) -> usize {
let s = self.as_u32_slice();
return s[INDEX_NUM_SHIFTED_OFF] as usize;
}
fn set_end(&mut self, index: usize, end: usize) {
let s = self.as_u32_slice_mut();
s[INDEX_OFFSETS + index] = end as u32;
@ -120,7 +143,12 @@ impl SharedQueue {
} else {
self.reset();
}
debug!(
"rust:shared_queue:shift: num_records={}, num_shifted_off={}, head={}",
self.num_records(),
self.num_shifted_off(),
self.head()
);
Some(&self.bytes[off..end])
}
@ -128,7 +156,7 @@ impl SharedQueue {
let off = self.head();
let end = off + record.len();
let index = self.num_records();
if end > self.bytes.len() {
if end > self.bytes.len() || index >= MAX_RECORDS {
debug!("WARNING the sharedQueue overflowed");
return false;
}
@ -138,6 +166,12 @@ impl SharedQueue {
let u32_slice = self.as_u32_slice_mut();
u32_slice[INDEX_NUM_RECORDS] += 1;
u32_slice[INDEX_HEAD] = end as u32;
debug!(
"rust:shared_queue:push: num_records={}, num_shifted_off={}, head={}",
self.num_records(),
self.num_shifted_off(),
self.head()
);
true
}
}
@ -213,4 +247,16 @@ mod tests {
assert_eq!(q.shift().unwrap().len(), 1);
assert_eq!(q.size(), 0);
}
#[test]
fn full_records() {
let mut q = SharedQueue::new(RECOMMENDED_SIZE);
for _ in 0..MAX_RECORDS {
assert!(q.push(&alloc_buf(1)))
}
assert_eq!(q.push(&alloc_buf(1)), false);
// Even if we shift one off, we still cannot push a new record.
assert_eq!(q.shift().unwrap().len(), 1);
assert_eq!(q.push(&alloc_buf(1)), false);
}
}

View file

@ -6,6 +6,21 @@ function assert(cond) {
}
}
// Check overflow (corresponds to full_records test in rust)
function fullRecords(q) {
q.reset();
const oneByte = new Uint8Array([42]);
for (let i = 0; i < q.MAX_RECORDS; i++) {
assert(q.push(oneByte));
}
assert(!q.push(oneByte));
r = q.shift();
assert(r.byteLength == 1);
assert(r[0] == 42);
// Even if we shift one off, we still cannot push a new record.
assert(!q.push(oneByte));
}
function main() {
const q = Deno.core.sharedQueue;
@ -56,7 +71,10 @@ function main() {
assert(q.numRecords() == 0);
assert(q.size() == 0);
fullRecords(q);
Deno.core.print("shared_queue_test.js ok\n");
q.reset();
}
main();