-
Notifications
You must be signed in to change notification settings - Fork 394
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
Latest build and issues with promise joining #345
Comments
Hey @jefflage, this is very strange. If there were a real error on line 163 then it's likely that nothing in when.js would work at all. Unit tests are all passing locally and on travis, so my intuition is that this particular stack trace may be obscuring some other kind of problem. Can you let me know what version of when you were upgrading from and what version you upgraded to? That may shed some light. Another thing to try is to enable Also, 3.4.2 fixed a problem that could have caused certain unhandled promise errors to be silent in previous versions. In 3.4.2, those will be loud, so I wonder if it's possible if this error has been there, but was not being reported in previous version--hopefully with more information we can figure it out. BTW, what is "bootstrap" in this case? I'm assuming it's not twitter bootstrap ... is it one of your own packages? |
I'm also getting this error. I thought that this was our fault. But today I've seen this happening in a completely different application. |
@tsouza and @jefflage Can you guys provide more information? I don't think I have enough to go on to begin debugging this, as I'm not able to reproduce it.
Any help you guys can provide will help me start to look into this, but right now I feel like I don't have enough info. Thanks! |
What version(s) of when.js are you using when the error occurs?
Can you provide more context about the error: at least the complete stack trace
Are you able to share the bit of actual application code that seems to trigger the error?
|
@tsouza Thanks for the info.
Is your error identical to @jefflage's? ie the stack trace ends with the same line number (163) in the same file (when/lib/makePromise.js) and same function (Promise._beget)?
I understand about sharing code. If you could put together a small example that reproduces the problem, that'd be extremely valuable, too! |
Hi Brian, I can confirm that is on the same line. I could share code, but I don't think it would be relevant. The bug is not Cheers On Tue, Jul 29, 2014 at 4:48 PM, Brian Cavalier notifications@github.com
|
Brian, I'll try to find a code snippet that reproduces the bug 100% of the On Tue, Jul 29, 2014 at 4:48 PM, Brian Cavalier notifications@github.com
|
TypeError: object is not a function
at Promise._beget (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/when/lib/makePromise.js:163:16)
at Promise.then (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/when/lib/makePromise.js:137:17)
at Promise.catch (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/when/lib/makePromise.js:153:16)
at Promise.catch.Promise.otherwise (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/when/lib/decorators/flow.js:36:22)
at Object.convert_from_ad_to_application_entitlements [as entitle] (/usr/hs/release/amber/amber/node_modules/entitlements/lib/parser.js:33:12)
at parse_entitlements (/usr/hs/release/amber/amber/node_modules/entitlements/lib/express/middleware.js:24:26)
at Layer.handle [as handle_request] (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/express/lib/router/layer.js:76:5)
at next (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/express/lib/router/route.js:100:13)
at Route.dispatch (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/express/lib/router/route.js:81:3)
at Layer.handle [as handle_request] (/usr/hs/release/amber/amber/node_modules/bootstrap/node_modules/express/lib/router/layer.js:76:5)
function convert_from_ad_to_application_entitlements (user, create_defaults, next) {
if (entitlements_have_been_parsed(user))
return next();
add_special_demo_entitlements(user);
var ad_entitlements = user.entitlements;
user.entitlements = [];
application_config.load_all().then(function(all_application_configs){
_.keys(ad_entitlements).forEach(function (application_code) {
convert_entitlement_for_application(application_code, all_application_configs, user, ad_entitlements);
});
build_simple_entitlements_hashes(user);
prune_environments_list(user);
user.has_multiple_clients = Object.keys(user.simple_entitlements.by_client).length > 1; //user.environments.length > 1;
next();
}).otherwise(next);
function entitlements_have_been_parsed (user) {
return Array.isArray(user.entitlements);
}
function convert_entitlement_for_application (application_code, all_application_configs, user, ad_entitlements) {
var application_config = _.findWhere(all_application_configs,{code:application_code});
if (application_config)
user.entitlements.push(create_application_entitlement_from_application_config(application_config));
else if (create_defaults)
user.entitlements.push(create_assumed_citrix_app(application_code, ad_entitlements[application_code]));
function create_application_entitlement_from_application_config (config) {
var entitlement = config;
create_environment_entitlements_for_application();
return entitlement;
function create_environment_entitlements_for_application () {
entitlement.environments = [];
for (var i = 0; i < ad_entitlements[application_code].length; i++) {
var env = ad_entitlements[application_code][i];
if (env.indexOf('PRODBETA') != -1)
log.warning('dropping ' + env + ' for ' + application_code + ' from ' + user.username);
else
entitlement.environments.push({name: env});
}
entitlement.environments = _.sortBy(
entitlement.environments,
function (x) {
return x.name.toLowerCase();
}
);
}
}
}
function create_assumed_citrix_app (code, envs) {
var info = {};
info.name = code;
info.citrix = true;
info.flash = false;
info.code = code;
info.multi_instance = (envs && envs.length > 0);
if (info.multi_instance) {
info.environments = [];
for (var i = 0; i < envs.length; i++)
info.environments.push({name: envs[i]});
}
return info;
}
} note this function is called by an express route handler. i suppose it is possible that there is an error in express that is occasionally resulting in as far as |
Brian, just a note. I do not use express in any application that triggers On Tue, Jul 29, 2014 at 4:57 PM, Jeff Lage notifications@github.com wrote:
|
Definitely appreciate the additional info, guys! @jefflage I'm looking at the code now. |
@jefflage quick q: can you point out line 33 in entitlements/lib/parser.js ? That's the line specifically mentioned in the stack trace just before it enters when.js code from you application code. Thanks. UPDATE: I'll assume it's this line, since it's the only one that calls }).otherwise(next); |
|
Got it, thanks. I'm trying a few tests involving |
yeah that was a shot in the dark, but from digging into your code it seems like a red herring. it seems to think that |
Yeah, I'm wondering about that as well. I'll look into that angle a bit more, too. Thanks. |
maybe some backstory on what our code is doing:
we don't use |
Thanks for the explanation.
It shouldn't cause problems. In most other promise libs, not calling |
@briancavalier i pushed a change to UAT just now to enable |
Awesome, thanks! Looking more at the code, the most obvious way I can see for It's hard to see how the code could even get that far, though, if |
@briancavalier i got the error in dev today. here is the stack trace (seems to be the same was before): 2014-07-30T15:16:40.874Z - error: TypeError: object is not a function
at Promise._beget (/Users/jlage/dev/web/server/bootstrap/node_modules/when/lib/makePromise.js:163:16)
at Promise.then (/Users/jlage/dev/web/server/bootstrap/node_modules/when/lib/makePromise.js:137:17)
at Promise.catch (/Users/jlage/dev/web/server/bootstrap/node_modules/when/lib/makePromise.js:153:16)
at Promise.catch.Promise.otherwise (/Users/jlage/dev/web/server/bootstrap/node_modules/when/lib/decorators/flow.js:36:22)
at load_distinct_values_for_column (/Users/jlage/dev/web/server/datastream/src/express/controller.js:40:18)
at Layer.handle [as handle_request] (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/layer.js:76:5)
at next (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/route.js:100:13)
at require_environment (/Users/jlage/dev/web/server/entitlements/lib/express/middleware.js:8:24)
at Layer.handle [as handle_request] (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/layer.js:76:5)
at next (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/route.js:100:13) and then just a little further down in the console, i see the output from [promises] Unhandled rejections: 1
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:689:11)
at ServerResponse.header (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/response.js:595:10)
at ServerResponse.send (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/response.js:143:12)
at ServerResponse.json (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/response.js:229:15)
at ServerResponse.send (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/response.js:131:21)
from execution context:
at Promisified_Redis_Connection.<anonymous> (/Users/jlage/dev/web/server/redis-replicant/src/simple/connection.js:37:17)
at try_callback (/Users/jlage/dev/web/server/redis-replicant/node_modules/redis/index.js:592:9)
at RedisClient.return_reply (/Users/jlage/dev/web/server/redis-replicant/node_modules/redis/index.js:685:13)
at HiredisReplyParser.<anonymous> (/Users/jlage/dev/web/server/redis-replicant/node_modules/redis/index.js:321:14)
at HiredisReplyParser.EventEmitter.emit (events.js:95:17)
at HiredisReplyParser.execute (/Users/jlage/dev/web/server/redis-replicant/node_modules/redis/lib/parser/hiredis.js:43:18)
at RedisClient.on_data (/Users/jlage/dev/web/server/redis-replicant/node_modules/redis/index.js:547:27)
from execution context:
at pipeline (/Users/jlage/dev/web/server/bootstrap/node_modules/when/pipeline.js:40:10)
at IndexTraverser.traverse_index (/Users/jlage/dev/web/server/redis-accessor/lib/index-traverser.js:39:12)
at IndexTraverser.traverse_index_to_hash (/Users/jlage/dev/web/server/redis-accessor/lib/index-traverser.js:66:17)
at Object.load_for (/Users/jlage/dev/web/server/datastream/src/refdata/index-metadata.js:6:30)
at Object.distinct_values_for (/Users/jlage/dev/web/server/datastream/src/refdata/index-metadata.js:12:25)
at Object.distinct_values_for (/Users/jlage/dev/web/server/datastream/src/refdata/index.js:32:35)
at load_distinct_values_for_column (/Users/jlage/dev/web/server/datastream/src/express/controller.js:38:32)
at Layer.handle [as handle_request] (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/layer.js:76:5)
at next (/Users/jlage/dev/web/server/bootstrap/node_modules/express/lib/router/route.js:100:13) though i have to admit, its not obvious to me that these are related, but it may be to you |
Thanks @jefflage. It's not obvious to me either how the two might be related. However, the fact that the original error is not tracked by It would be interesting to see what happens if the second error (the one being reported by |
Hi Brian, No
|
yes: var Promise = require('when').Promise;
var timeoutCount = 0;
var origTimeout = Promise.prototype.timeout;
Promise.prototype.timeout = function(ms, e) {
increment();
return origTimeout.apply(this, arguments).finally(decrement);
};
function increment() {
timeoutCount +=1;
log.debug('timeout set: ' + timeoutCount);
}
function decrement() {
timeoutCount -= 1;
log.debug('timeout cleared: ' + timeoutCount);
} you and i discussed adding it to try to track down some odd behavior i was saying around timeouts. |
i guess replying via email doesn't do the markdown formatting! |
@tsouza Thanks for confirming. @jefflage Right, I remember you're directly overriding timeout to help debug. That should be fine. I'm curious about actual inheritance, for example: var Promise = require('when').Promise;
function MyPromiseSubType(whatevs) {
Promise.apply(this, arguments);
// ...
}
MyPromiseSubType.prototype = Object.create(Promise.prototype);
// ... Sounds like you're not doing that, but just wanted to make sure.
Wow, yeah, weird. |
@jefflage @tsouza on which specific platforms and versions are you seeing this error? Note: version is very important, as Node 0.8, 0.10, and 0.11 output different error messages under the same conditions! It's likely that is due to different underlying versions of v8, so may affect Chrome error message as well. Thanks! |
0.10.29 in dev and 0.10.26 in prod On Jul 30, 2014, at 5:01 PM, Brian Cavalier notifications@github.com wrote:
|
Same here
|
granted i don’t have a large sample size here, but since i added just thought i’d share. On Jul 30, 2014, at 3:53 PM, Brian Cavalier notifications@github.com wrote:
|
Woohoo! Thanks @jefflage! That's pretty convincing to me that the ultimate cause is v8 inlining or optimization of some sort. Unfortunately, leaving the I wish I could recreate this problem locally so that I didn't have to ask you guys to keep trying stuff. But I've yet to find a way. @tsouza @pbarnes Have you guys had any luck creating smaller test cases? Our next steps could be to run a series of more focused experiments, each of which tests a specific v8 optimization, until we narrow down the cause to a particular v8 feature. For example, as @stefanpenner suggested above, we could add a large comment to increase the text size of the function, which will prevent v8 from inlining it. If the error stays away in that case, we know (100%? not sure) it's because of inlining. I'm more than happy to keep making branches, if you're willing to give them a try, until we find the minimal solution. Please let me know if you'd be ok with that. 1: Interestingly, I did run some benchmarks and it seemed not to affect performance on node 0.10.28. I'm not convinced that |
@briancavalier quick update, still no errors. on a side note, have you ever looked into node modules that can parse 'function bodies'. meaning you can do something like this: function foo(bar) {
console.log(bar);
}
console.log(bar.toString()) which will spit out the source for the function declaration. have you ever looked at libraries that can parse that output to tell you things like the names of the parameters the function is expecting? I'm only asking as i could see where you might have wanted something like that for when. |
Running into the same issue with 3.5.0. Can't reproduce reliably, but have continuously seen this sporadically happen in dev for the last few weeks. |
@KidkArolis We've concluded that v8 is incorrectly optimizing a function inside of |
@jefflage Sorry for not responding sooner. I don't know of any libs that specifically parse function bodies, other than the usual AST parsers like esprima. Parsing just the function declaration to extract parameters names is pretty simple: var paramsRx = /\(([^)]*)/;
var match = paramsRx.exec(foo.toString());
var paramNames = match ? match[1].split(/\s*,\s*/) : []; We use that technique over in most.js's |
Updating from 3.5 to 3.6 started causing "TypeError: object is not a function" in urequire latest beta, in places I had not problems before, like this |
@anodynos |
@anodynos Another thing you could do is try master. It has a greatly simplified |
I am not using |
Good news - it seems to fail more predictably on Windows / non SSD disk. You never know... |
That what I got so far (
The last call of urequire's is in |
@anodynos Thanks for the all that info!
Ah, yes, that's very helpful! That line turns out to be the exact same line (although it's line number has changed in 3.6.0 due to refactoring) on which the error was reported by others in this thread. So, it appears you are being bitten by the same v8 optimization bug :( One workaround is to insert the following as the first line of the
Yes, literally an empty try/finally. This prevents all but the most recent versions of v8 from optimizing that method, and thus it won't generate invalid optimized code. The bug is sporadic (as you've seen!) and very difficult to reproduce, so I haven't been able to duplicate it locally. However, others have had success with this workaround. Sorry, I realize that kinda stinks. Please politely ask the v8 maintainers to fix this :) Please give it a try and let me know if it helps. I may have to bite the bullet and somehow integrate a workaround into the codebase, which would make me sad, but might be worth it. |
This should be patched before more people run into it IMHO.. At least until On Wed, Nov 12, 2014, 06:03 Brian Cavalier notifications@github.com wrote:
|
Thanks for the info @briancavalier - I think I'll stick to 3.5.0 for now that seems to somehow avoid the bug. I believe like @KidkArolis that the patch should go in ;-) Another strange thing I noticed that might help: that last |
FYI, this DID NOT help:
Only reverting to 3.5.0 solves it. Testing on node v0.10.33 on Windows 7 x64, it fails more often than same version in Kubuntu 14 x64, if that's useful. |
Hmmm, what version of node? |
I was just updating the above comment - Testing on node v0.10.33 on Windows 7 x64, it fails more often than same version in Kubuntu 14 x64, if that's useful. |
@jefflage @KidkArolis @tsouza @stefanpenner v8 bug report filed: https://code.google.com/p/v8/issues/detail?id=3692 Please +1 it :) |
Voted! |
ditto
|
@jefflage @tsouza @pbarnes @KidkArolis 3.6.2 just landed with a workaround for this. Thank you all for your help in debugging this, and for your patience! Please let me know if you encounter the failure again after updating. |
Apparently some people have been seeing knock-on effects of cujojs/when#345.
we've recently upgraded in the latest build of when and we've started to some sporadic errors from when that were not getting before. here is a part of a stack:
its not happening all of the time and it's happening in different places in our code. it was not happening before we upgraded.
The text was updated successfully, but these errors were encountered: