-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Access violation in nodejs when restarting a listening server #25365
Comments
@Arno-v ... thanks for the code but it's not clear from the code exactly how to recreate the behavior you're seeing. Can you provide a more complete snippet? |
Here's an actually readable and usable version of the code:
@Arno-v could you please clarify if you're talking about an error in the means of: "Error: listen EADDRINUSE 0.0.0.0:443", or "Segmentation Fault"? Thanks |
@KenanSulayman it happens in: https://github.com/joyent/node/blob/master/src/stream_wrap.cc on line 492. The variable wrap = NULL. I modified the code in stream_wrap.cc to so it would test for wrap==NULL, and this would prevent node from crashing, however, the server would not start listening again. The restartableHttps object is used in a much larger program. It is used because we want to be able to switch to a different configuration in runtime. We want to close the listening server, and restart it with different certificates. The command to switch comes from another connection on localhost. We use a pattern in which we keep track of the connections, and destroy the connections via socket.destroy if we want to switch the configuration. I have created a sample program and directories which exhibit the behaviour. where can I upload this zip-file? |
https://github.com/EricSmekens/testNodeJS Here is the sample project. Certificates probably need to updated for your machine name. |
To be clear, to reproduce, run program and visit http://localhost/SwitchServer |
Addition: In test.js, you want to change 'nlltvriesa01' to your machinename. To reproduce it, open a link to https://$MACHINENAME_HERE$/test.html and then on a second tab/browser. You will have to bypass the cerfificate security, or make your own. Navigate to http://localhost/SwitchServer on the other tab. (Switching server while there is a connection seems to be the problem.) |
Issue also reproduceable on Windows 8.1 - Node v0.12.4. Node silently terminates. |
I finally found the problems. It is part the application, and part node.js not handling a strange situation properly. StreamWrap* wrap = Unwrap<StreamWrap>(args.Holder());
if (wrap == NULL)
{
args.GetReturnValue().Set(EIO);
return;
} This way I found out that a the js application tried to send a response over a destroyed socket, res is being send AFTER the server has been restarted: var counter=0;
app.get('/TestPoll',function(req,res){
counter++;
setTimeout(function(){
res.send({counter:counter})
},500);
}); When I look at the rest of the stream_wrap.cc source, it seems to me that the line StreamWrap* wrap = Unwrap<StreamWrap>(args.Holder()); Could initialize wrap to NULL on more places. |
I have also been looking at the problem, and I am able to reproduce on Windows and Linux. It does look like the issue is caused by writing to a socket that has been destroyed. Ideally, I/O operations on sockets should be checking to see if they have been destroyed. At the moment I'm working on a simplified test case to reproduce the issue |
I think I have this tracked down and it has to do with the way file io is processed by the thread pool. Basically, when the write to the socket occurs, it is still open (and thus the checks all pass). A request is then put in the queue to be processed by a worker in the thread pool. Before the request gets picked up, the socket gets closed, thus when the threadpool worker starts the request it segfaults. Ideally, |
This aught to fix the issue eed9392 |
I was looking at this some more and my previous conclusion was wrong. In the end the problem is that you are closing the underlying socket and the server tries to write to the TLS socket (which shares a handle, but is not notified when the regular socket is destroyed). |
@dnakamura ... given your most recent comment, is the fix in eed9392 still necessary? |
The problem remains that nodejs crashes and does not throw an exception in On Thu, Jun 25, 2015 at 10:47 PM, James M Snell [email protected]
|
I think so as well, at this moment nodejs silently terminates. |
@jasnell Strinctly speaking no, eed9392 is not required. However, it is still probably useful to keep so that any future bugs will fail gracefully rather than segfault. @EricSmekens The ideal solution would be to modify the tls socket code to detect when you have closed the underlying handle. However you do bring up another interesting point, why does node silently terminate rather than printing out the standard segfault info? |
@dnakamura For me, (Node 0.12.5), it is not printing any error/info when this occurs. If I am using 'secureConnection' instead of 'connection', then I will receive an error and it seems that it occurs fewer times. (EADDRINUSE). |
@EricSmekens ... just to cover all the bases, can you check to see if the same issue occurs in the latest io.js? |
@EricSmekens sounds like you are getting that error because you are trying to bind to the server socket before it has been released. Looking at my code I added a delay, so maybe I was hitting the same problem. Relevant code:
Also note, I moved |
Also, for anybody thats interested, the problem arises because while the TLS socket, and the normal socket share the file handle, they maintain little no level of coordination. My initial solution was to add a line to the TLSSocket constructor
Which means that a second call to |
Nodejs version 0.12.3
Windows 7 and Windows 2012 x64
For our application we need a https or spdy server which can be restarted using a path on the filesystem. On the first call to open() this functions OK, however on the second call it often crashes nodejs. The crash occurs in
https://github.com/joyent/node/blob/master/src/stream_wrap.cc
on line 492. The variable wrap = NULL.
We have tried this with https as well as with spdy.
Code:
The text was updated successfully, but these errors were encountered: