After Sending a Lot, My Send() Call Causes My Program to Stall Completely. How Is This Possible

After sending a lot, my send() call causes my program to stall completely. How is this possible?

The kernel keeps a finite buffer for sending data. If the receiver isn't receiving, that buffer will fill up and the sender will block. Could that be the problem?

I'm using tcp for very many small sends, should I turn off Nagles algorithm? (People also know this as TCP_NODELAY)

TCP_NODELAY might help latency of small packets from sender to receiver, but the description you gave points into different direction. I can imagine the following:

  • Sending more data than receivers actually consume - this eventually overflows sender's buffer (SO_SNDBUF) and causes the server process to appear "stuck" in the send(2) system call. At this point the kernel waits for the other end to acknowledge some of the outstanding data, but the receiver does not expect it, so it does not recv(2).

There are probably other explanations, but it's hard to tell without seeing the code.

Server dies on `send` if client was closed with Ctrl+c

When you call send() on an already closed connection, the operating system may issue SIGPIPE to your process. Usually the default handler for SIGPIPE is to kill your process.

In order to prevent this from occurring, you can either ignore the signal (e.g., with signal(SIGPIPE, SIG_IGN) or sigignore(SIGPIPE)), or you can pass the MSG_NOSIGNAL option to send():

int send_result = send(newfd, ok, 3, MSG_NOSIGNAL);
if (send_result >= 0) {
/* okay, but check if all your data got sent! */
if (send_result < 3) /* ...do something */;
} else {
switch (errno) {
/* ... */
case EPIPE:
/* sending on a closed connection... */
}
}

Now, instead of issuing SIGPIPE, the send() call will fail, and errno will be set to EPIPE.

Java socket output has delayed first message

Your code appears to send the JOIN commands every time it goes around the while loop, which appears to be once for every line the server sends you, until you finally get the response from the server confirming that you've joined the channel.

This means you'll end up sending those JOIN commands a very large number of times. IRCDs are designed to only handle a set rate of commands per second from each client - so this is probably what's lagging you (your later commands end up on the end of a very long queue filled with lots of JOIN commands).

Instead, you should only send the JOIN commands once only, by setting the flag as soon as you send them:

boolean sent_join = false;
boolean joined = false;

while ((line = getInput().readLine()) != null) {
if (!sent_join) {
getOutput().println("JOIN #PrinZ");
getOutput().println("JOIN #Trinorae");
sent_join = true;
}

if (line.contains("JOIN :#prinz")) {
System.out.println("JOINED #prinz = true");
joined = true;
}
}

Note that you can't send your JOIN commands until after you're registered, which is indicated by an 001 numeric, so you may need to wait for that line before sending them.

Note that line.contains is not a very robust way of parsing IRC messages. If I send you a message that contained "JOIN :#prinz", it'd trigger on that too. You should be breaking each incoming message up into source, command, destination and arguments.

Res.Render Is Stalling

The main problem I see is that your app.get("/posts/:postName", ...) route needs to always send one and only one http response. The way it is coded now, it will send no response if a matching post isn't found and it will attempt to send multiple responses if more than one is found. Both conditions are a problem.

Here's one way to fix that:

app.get("/posts/:postName", (req, res) => {
const requestedTitle = req.params.postName.toLowerCase();
for (let post of posts) {
const storedTitle = post.title.toLowerCase();
if (requestedTitle === storedTitle) {
res.render("post", {
post: post
});
return;
}
}
// send some sort of response here with a 404 status
res.sendStatus(404);
});

As a possible explanation for the server behavior you saw, the browser will only send so many requests in-flight at the same time to the same host. So, if with your original code, you are playing with URLs that don't have matching posts, those will not get responses sent back to the browser from the server and those requests will still be waiting for a response. Eventually the browser will hit the max requests that it will send to your host until some of them finish. Thus, it will appear that your server becomes non-responsive to new requests, when in reality it's just waiting for prior requests to finish. You must always send one and only one response from your server to each incoming http request.


I assume this posts array is probably just a temporary storage mechanism, but it would be a lot more efficient if you replaced the array with a Map object with the lowercase title as the key. Then, you could just directly lookup the matching title on the Map object with one map.get() operation rather than looping through the whole array.



Related Topics



Leave a reply



Submit