             # read upto len bytes and store into mmap'd buffer at address
             block_addr = rs.block_addr(address)
             buf = new Buffer len
-            bytes_read = fs.readSync(fd, buf, 0, len)
-            if DataView?
-              for i in [0...bytes_read] by 1
-                rs.mem_blocks[block_addr].setInt8(i, buf.readInt8(i))
-            else
-              for i in [0...bytes_read] by 1
-                rs.mem_blocks[block_addr+i] = buf.readInt8(i)
-            return bytes_read
+            rs.async_op (cb) ->
+              fs.read fd, buf, 0, len, (err, bytes_read) ->
+                if DataView?
+                  for i in [0...bytes_read] by 1
+                    rs.mem_blocks[block_addr].setInt8(i, buf.readInt8(i))
+                else
+                  for i in [0...bytes_read] by 1
+                    rs.mem_blocks[block_addr+i] = buf.readInt8(i)
+                cb bytes_read
           o 'preClose0(Ljava/io/FileDescriptor;)V', (rs, fd_obj) ->
             # NOP, I think the actual fs.close is called later. If not, NBD.
         ]

              # this is a real file that we've already opened
              pos = _this.$pos
              buf = new Buffer n_bytes
              # if at end of file, return -1.
              filesize = fs.fstatSync(fd).size
              if filesize > 0 and pos >= filesize-1
                return -1
              bytes_read = fs.readSync(fd, buf, 0, n_bytes, pos)
              # not clear why, but sometimes node doesn't move the file pointer,
              # so we do it here ourselves
              _this.$pos += bytes_read
              byte_arr.array[offset+i] = buf.readUInt8(i) for i in [0...bytes_read] by 1
              return if bytes_read == 0 and n_bytes isnt 0 then -1 else bytes_read
            # reading from System.in, do it async
            rs.async_op (cb) ->
              rs.async_input n_bytes, (bytes) ->

            fd = fd_obj.get_field rs, 'Ljava/io/FileDescriptor;fd'
            rs.java_throw rs.get_bs_class('Ljava/io/IOException;'), "Bad file descriptor" if fd is -1
            unless fd is 0
              rs.async_op (cb) ->
                fs.fstat fd, (err, stats) ->
                  bytes_left = stats.size - _this.$pos
                  to_skip = Math.min(n_bytes.toNumber(), bytes_left)
                  _this.$pos += to_skip
                  cb gLong.fromNumber(to_skip), null
              return
            # reading from System.in, do it async
            rs.async_op (cb) ->
              rs.async_input n_bytes.toNumber(), (bytes) ->
