Cześć,
napisałem oprogramowanie w c++ które uruchamiam na raspberry, Program otwiera pliki, zaczytuje lub loguje dane i je zamyka. Używam też komunikacji tcp z dwoma urządzeniami. Po pewnym czasie działania programu dostaje komunikat: "could not create socket: Too many open files"
Czy zamykam gdzieś błędnie jakiś plik lub socket? Program działa w kilku wątkach i kilka wątków też odwołuje się np do jednego logera i pliku, czy powienienem to jakoś zabezpieczyć?
Dla użytkownika aktualnie ustawiony jest limit otwartych plików na 1024. Jest to bardzo dużo i nie rozumiem w jaki sposób aktualnie jestem w stanie to wypełnić.
Kod logera:
inline string get_current_date_time(string arg_s) {
time_t l_now = time(0);
struct tm l_tstruct;
char l_buf[80];
l_tstruct = *localtime(&l_now);
if (arg_s == "now")
strftime(l_buf, sizeof(l_buf), "%Y-%m-%d %X", &l_tstruct);
else if (arg_s == "date")
strftime(l_buf, sizeof(l_buf), "%Y-%m-%d", &l_tstruct);
return string(l_buf);
};
inline void logger(string arg_log_msg) {
try {
string filePath = get_current_date_time("date") + ".txt";
string now = get_current_date_time("now");
ofstream ofs(filePath.c_str(), std::ios_base::out | std::ios_base::app);
ofs << now << " [" + g_raspberry_temp + "] " << arg_log_msg << '\n';
ofs.close();
}
catch (...) {
cout << "Logger ERROR" << endl;
}
}
Kod czytający temperature cpu raspberry:
string raspberry_temp() {
FILE* l_temperature_file;
double l_T;
l_temperature_file = fopen("/sys/class/thermal/thermal_zone0/temp", "r");
if (l_temperature_file == NULL) {
throw 4;
}
fscanf(l_temperature_file, "%lf", &l_T);
l_T /= 1000;
// printf("The temperature is %6.3f C.\n", T);
fclose(l_temperature_file);
string l_tmp = to_string(l_T);
return l_tmp.substr(0, l_tmp.find(".") + 3);
}
Kod połączenia tcp:
int tcp_client(char* arg_message, int &sock) {
int l_valread, l_client_fd;
struct sockaddr_in l_serv_addr;
try {
if (sock < 0) {
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
logger(" Socket creation error");
throw 101;
}
l_serv_addr.sin_family = AF_INET;
l_serv_addr.sin_port = htons(strtol(g_config_frontrnd_port.c_str(), NULL, 0));
if (inet_pton(AF_INET, g_config_frontend_ip.data(), &l_serv_addr.sin_addr)
<= 0) {
logger("Invalid address/ Address not supported");
throw 102;
}
if ((l_client_fd
= connect(sock, (struct sockaddr*)&l_serv_addr,
sizeof(l_serv_addr)))
< 0) {
logger("Connection Failed");
throw 103;
}
logger("Polaczono z frontendem");
}
if(send(sock, arg_message, strlen(arg_message), 0) < 0) throw 104;;
}
catch (int e) {
close(sock);
sock = -1;
if (e == 101) logger("CANT CONNECT TO FRONTEND : Exception Nr. 1");
else if (e == 102) logger("CANT CONNECT TO FRONTEND : Exception Nr. 2");
else if (e == 103) logger("CANT CONNECT TO FRONTEND : Exception Nr. 3");
else if (e == 104) logger("CANT CONNECT TO FRONTEND : BORKEN PIPE");
else logger("CANT CONNECT TO FRONTEND : Exception Nr. " + to_string(e));
logger("Utracono polaczenie z frontendem");
return e;
}
}
Kod czytania json
void read_language(string arg_file) {
logger("Zaczytanie konfiguracji z pliku " + arg_file);
std::ifstream l_t(arg_file);
std::stringstream l_buffer;
l_buffer << l_t.rdbuf();
l_t.close();
Json::Reader reader;
Json::Value obj;
reader.parse(l_buffer, obj);
g_prss_button1 = obj["Test_button_1"].asString();
g_prss_button2 = obj["Test_button_2"].asString();
g_prss_button3 = obj["Test_button_3"].asString();
}