Giter VIP home page Giter VIP logo

Comments (11)

rhashimoto avatar rhashimoto commented on September 27, 2024 2

@getvictor I suspect this occurs because your virtual table modules throw an error here. It looks like when this happens the WebAssembly stack is not properly unwound and subsequent calls into WebAssembly will start with that part of the stack unavailable. Eventually all these now inaccessible stack regions take up all the allotted stack space.

Can you please try returning a valid SQLite result code from all module methods, and see if that fixes the problem?

Investigative details follow:

I patched my SQLite source to log the stack address when sqlite3_prepare() is called like this:

SQLITE_API int sqlite3_prepare_v2(
  sqlite3 *db,              /* Database handle. */
  const char *zSql,         /* UTF-8 encoded SQL statement. */
  int nBytes,               /* Length of zSql in bytes. */
  sqlite3_stmt **ppStmt,    /* OUT: A pointer to the prepared statement */
  const char **pzTail       /* OUT: End of parsed string */
){
  int rc;
  printf("sqlite3_prepare_v2 %p %s\n", &rc, zSql);
  ...

A couple iterations of output looks like this:

sqlite3_prepare_v2 0x906b8 SELECT * from chrome_extensions
sqlite3_prepare_v2 0x8f938 SELECT*FROM"main".sqlite_master ORDER BY rowid
sqlite3_prepare_v2 0x906b8 
sqlite3_prepare_v2 0x906b8 SELECT * from disk_info
sqlite3_prepare_v2 0x906b8 
sqlite3_prepare_v2 0x906b8 SELECT * FROM network_interfaces
sqlite3_prepare_v2 0x8fdf8 SELECT * FROM os_version
sqlite3_prepare_v2 0x8fdf8 
sqlite3_prepare_v2 0x8fdf8 SELECT * FROM osquery_info
sqlite3_prepare_v2 0x8fdf8 
sqlite3_prepare_v2 0x8fdf8 SELECT * FROM privacy_preferences
sqlite3_prepare_v2 0x8fdf8 
sqlite3_prepare_v2 0x8fdf8 SELECT * FROM screenlock
sqlite3_prepare_v2 0x8f538 SELECT * FROM system_info
sqlite3_prepare_v2 0x8f538 
sqlite3_prepare_v2 0x8f538 SELECT * FROM system_state
sqlite3_prepare_v2 0x8ec78 SELECT * FROM users
sqlite3_prepare_v2 0x8ec78 
sqlite3_prepare_v2 0x8ec78 SELECT * from chrome_extensions
sqlite3_prepare_v2 0x8ec78 
sqlite3_prepare_v2 0x8ec78 SELECT * from disk_info
sqlite3_prepare_v2 0x8ec78 
sqlite3_prepare_v2 0x8ec78 SELECT * FROM network_interfaces
sqlite3_prepare_v2 0x8e3b8 SELECT * FROM os_version
sqlite3_prepare_v2 0x8e3b8 
sqlite3_prepare_v2 0x8e3b8 SELECT * FROM osquery_info
sqlite3_prepare_v2 0x8e3b8 
sqlite3_prepare_v2 0x8e3b8 SELECT * FROM privacy_preferences
sqlite3_prepare_v2 0x8e3b8 
sqlite3_prepare_v2 0x8e3b8 SELECT * FROM screenlock
sqlite3_prepare_v2 0x8daf8 SELECT * FROM system_info
sqlite3_prepare_v2 0x8daf8 
sqlite3_prepare_v2 0x8daf8 SELECT * FROM system_state
sqlite3_prepare_v2 0x8d238 SELECT * FROM users
sqlite3_prepare_v2 0x8d238 

We expect the address when entering from JavaScript always to be the same, but instead we see it is lower after accessing network_interfaces, screenlock, and system_state virtual tables. Those specific virtual tables are suspiciously labeled as "bad_tables". Error logging from these tables is suppressed, but it appears likely these unlogged exceptions are skipping stack unwinding. That might be an Emscripten bug, or it might just be that you aren't supposed to do that.

from wa-sqlite.

getvictor avatar getvictor commented on September 27, 2024 1

I created a repo reproducing this issue: https://github.com/getvictor/fleetd-chrome

And video instructions: https://www.loom.com/share/603cb991739f4e54b1603e7fed1ff273?sid=e31ab9ee-9660-43bb-b477-9146b8fedff3

My build with TOTAL_STACK=2mb: github:getvictor/wa-sqlite#7430694

from wa-sqlite.

getvictor avatar getvictor commented on September 27, 2024 1

Removing throw worked. Closing issue. Thank you.

from wa-sqlite.

rhashimoto avatar rhashimoto commented on September 27, 2024

Answers to your questions:

  1. That would be one of my guesses. I'm not sure of the best way to monitor available memory in C.
  2. I don't know but I wouldn't think so.
  3. I don't think that will work because of the reason you state. You might be able to destroy the current WebAssembly module and instantiate a new one. I believe that should work but I've never done that so I don't know the details on the destroying part.
  4. I'm not sure yet. It's possible that messing with some build parameters would make it go away, but I'd be nervous that it just puts off the problem.

Some questions for you:

  1. What build are you using (default or Asyncify)? Are you using a custom build, and if so how is it customized?
  2. What VFS (if not the default)?
  3. You're using a module (virtual table), is that correct? If yes, are you making any API calls from module methods?
  4. Can you list the wa-sqlite wrapped APIs you call, i.e. from this list regularly (after all the initialization)? Is it only exec()?
  5. Does your SQL change over time or are you just issuing the same query over and over?
  6. Does your SQL modify the database or only read?
  7. Aren't Chrome extensions basically service workers now? How do you keep an extension context alive for two days?
  8. If you're using any SQL PRAGMA statements, can you list them?

from wa-sqlite.

rhashimoto avatar rhashimoto commented on September 27, 2024

The error typically takes ~2 days to show up, where the database is used for ~10 queries per minute. Once this error happens, it continues happening for each subsequent exec call.

That's roughly 30K queries, yes? Is it possible to log all the SQL you submit, including any setup, so we can just replay it and reproduce the error that way? Or even better, can you write a succinct generator that will initialize the schema and database and produce an arbitrary number of simulated queries?

from wa-sqlite.

getvictor avatar getvictor commented on September 27, 2024

I will put together a detailed answer to your questions tomorrow. A dedicated Chromebook is always on and only running my extension.

I rebuilt wa-sqlite with TOTAL_STACK=2mb and so far it hasn't hit this issue.

from wa-sqlite.

getvictor avatar getvictor commented on September 27, 2024
  1. What build are you using (default or Asyncify)? Are you using a custom build, and if so how is it customized?

Asyncify

  1. What VFS (if not the default)?

Default

  1. You're using a module (virtual table), is that correct? If yes, are you making any API calls from module methods?

Yes, using 11 modules.

  1. Can you list the wa-sqlite wrapped APIs you call, i.e. from this list regularly (after all the initialization)? Is it only exec()?

exec() and virtual tables call result() inside xColumn() function

  1. Does your SQL change over time or are you just issuing the same query over and over?

It can change, but it is the same set of queries 95% of the time.

  1. Does your SQL modify the database or only read?

Only reads -- only SELECT statements.

  1. Aren't Chrome extensions basically service workers now? How do you keep an extension context alive for two days?

Dedicated Chromebook.

  1. If you're using any SQL PRAGMA statements, can you list them?

No

For reference, the relevant extension code is here:
https://github.com/fleetdm/fleet/blob/main/ee/fleetd-chrome/src/db.ts

I'll try and see if I can reproduce this issue faster.

from wa-sqlite.

rhashimoto avatar rhashimoto commented on September 27, 2024

I can see an error with the repo and the instructions. With a debug wa-sqlite build, I get:

Query (sql: "SELECT * FROM osquery_info") failed: RuntimeError: Aborted(RuntimeError: unreachable). "unreachable" may be due to ASYNCIFY_STACK_SIZE not being large enough (try increasing it)

ASYNCIFY_STACK_SIZE was one of my top suspects when I learned this is an Asyncify build. But this is a very simple query so I don't see why that should take a lot of stack space, and when I increased ASYNCIFY_STACK_SIZE all the way up to 8 MB (from 16 KB) the error persists. So I think this is not the problem. Or perhaps it could be part of the problem but not the only problem.

My other top suspect was memory leak. This also seems less likely now that it doesn't take days to reproduce. I have looked over the exec() code several times and I don't see a leak.

My new top suspect is one I didn't consider earlier: actual memory corruption in the virtual table structs. It's possible there is an error in translating JavaScript objects to C structs. I'll follow up on that. @getvictor In the reproduction repo, is there anything in those virtual tables when the error happens or are they empty?

from wa-sqlite.

getvictor avatar getvictor commented on September 27, 2024

The virtual tables should not be persisting any data. Their return values are either hardcoded, or they call chrome APIs to get their values. I think their values have to be re-translated from JS to C and back to JS on every SELECT.

from wa-sqlite.

rhashimoto avatar rhashimoto commented on September 27, 2024

@getvictor I was asking whether we expect those SELECTs to return any rows when we see the error. That is, do you think that result() is being called by any module before the error appears? I can check for myself if you don't know offhand.

from wa-sqlite.

rhashimoto avatar rhashimoto commented on September 27, 2024

Filed an Emscripten issue in case this is a bug.

Update: Not an Emscripten bug - don't throw on calls from SQlite WebAssembly to JavaScript, that produces undefined behavior.

from wa-sqlite.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.