AK: Add a ScopeGuard helper that invokes a callback when destroyed.

This is useful when you want to ensure some little thing happens when you
exit a certain scope.

This patch makes use of it in LibC's netdb code to make sure we close the
connection to the LookupServer.
This commit is contained in:
Andreas Kling 2019-06-07 09:18:21 +02:00
parent 4edc73ad1f
commit 69a6ce90df
Notes: sideshowbarker 2024-07-19 13:42:15 +09:00
2 changed files with 40 additions and 14 deletions

24
AK/ScopeGuard.h Normal file
View file

@ -0,0 +1,24 @@
#pragma once
namespace AK {
template<typename Callback>
class ScopeGuard {
public:
ScopeGuard(Callback callback)
: m_callback(move(callback))
{
}
~ScopeGuard()
{
m_callback();
}
private:
Callback m_callback;
};
}
using AK::ScopeGuard;

View file

@ -1,12 +1,13 @@
#include <AK/AKString.h>
#include <AK/Assertions.h>
#include <AK/ScopeGuard.h>
#include <Kernel/Net/IPv4.h>
#include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <netinet/in.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h> #include <unistd.h>
#include <AK/Assertions.h>
#include <AK/AKString.h>
#include <Kernel/Net/IPv4.h>
extern "C" { extern "C" {
@ -73,11 +74,15 @@ hostent* gethostbyname(const char* name)
if (fd < 0) if (fd < 0)
return nullptr; return nullptr;
auto close_fd_on_exit = ScopeGuard([fd] {
dbgprintf("closing fd\n");
close(fd);
});
auto line = String::format("L%s\n", name); auto line = String::format("L%s\n", name);
int nsent = write(fd, line.characters(), line.length()); int nsent = write(fd, line.characters(), line.length());
if (nsent < 0) { if (nsent < 0) {
perror("write"); perror("write");
close(fd);
return nullptr; return nullptr;
} }
@ -87,11 +92,9 @@ hostent* gethostbyname(const char* name)
int nrecv = read(fd, buffer, sizeof(buffer) - 1); int nrecv = read(fd, buffer, sizeof(buffer) - 1);
if (nrecv < 0) { if (nrecv < 0) {
perror("recv"); perror("recv");
close(fd);
return nullptr; return nullptr;
} }
buffer[nrecv] = '\0'; buffer[nrecv] = '\0';
close(fd);
if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1)) if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1))
return nullptr; return nullptr;
@ -129,18 +132,20 @@ hostent* gethostbyaddr(const void* addr, socklen_t addr_size, int type)
if (fd < 0) if (fd < 0)
return nullptr; return nullptr;
auto close_fd_on_exit = ScopeGuard([fd] {
close(fd);
});
IPv4Address ipv4_address((const byte*)&((const in_addr*)addr)->s_addr); IPv4Address ipv4_address((const byte*)&((const in_addr*)addr)->s_addr);
auto line = String::format("R%d.%d.%d.%d.in-addr.arpa\n", auto line = String::format("R%d.%d.%d.%d.in-addr.arpa\n",
ipv4_address[3], ipv4_address[3],
ipv4_address[2], ipv4_address[2],
ipv4_address[1], ipv4_address[1],
ipv4_address[0] ipv4_address[0]);
);
int nsent = write(fd, line.characters(), line.length()); int nsent = write(fd, line.characters(), line.length());
if (nsent < 0) { if (nsent < 0) {
perror("write"); perror("write");
close(fd);
return nullptr; return nullptr;
} }
@ -150,7 +155,6 @@ hostent* gethostbyaddr(const void* addr, socklen_t addr_size, int type)
int nrecv = read(fd, buffer, sizeof(buffer) - 1); int nrecv = read(fd, buffer, sizeof(buffer) - 1);
if (nrecv < 0) { if (nrecv < 0) {
perror("recv"); perror("recv");
close(fd);
return nullptr; return nullptr;
} }
if (nrecv > 1) { if (nrecv > 1) {
@ -158,7 +162,6 @@ hostent* gethostbyaddr(const void* addr, socklen_t addr_size, int type)
buffer[nrecv - 1] = '\0'; buffer[nrecv - 1] = '\0';
} }
buffer[nrecv] = '\0'; buffer[nrecv] = '\0';
close(fd);
if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1)) if (!memcmp(buffer, "Not found.", sizeof("Not found.") - 1))
return nullptr; return nullptr;
@ -175,5 +178,4 @@ hostent* gethostbyaddr(const void* addr, socklen_t addr_size, int type)
return &__gethostbyaddr_buffer; return &__gethostbyaddr_buffer;
} }
} }