summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_file.c
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-14 15:22:17 +0100
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2020-08-20 08:52:32 +0100
commit4b4c208d99358941cfe886bc1a87e38c2390f0bd (patch)
tree07f1aa535981c3da041b5cea6d25a2fcf2023b9a /src/lib/eina/eina_file.c
parentcef058c48b21c6effed8d6580876632b4344ec7f (diff)
ecore - don't do anything with heap between fork and exec
this avoids a possibgle deadlock if a malloc impl is holding a lock and has not released it at the time we fork. @fix
Diffstat (limited to '')
-rw-r--r--src/lib/eina/eina_file.c220
1 files changed, 187 insertions, 33 deletions
diff --git a/src/lib/eina/eina_file.c b/src/lib/eina/eina_file.c
index c8abe6d39a..e38bf5bfbb 100644
--- a/src/lib/eina/eina_file.c
+++ b/src/lib/eina/eina_file.c
@@ -21,6 +21,10 @@
21# include "config.h" 21# include "config.h"
22#endif 22#endif
23 23
24#ifndef _GNU_SOURCE
25# define _GNU_SOURCE
26#endif
27
24#include <stdlib.h> 28#include <stdlib.h>
25#include <string.h> 29#include <string.h>
26#include <stddef.h> 30#include <stddef.h>
@@ -1252,6 +1256,47 @@ eina_file_statat(void *container, Eina_File_Direct_Info *info, Eina_Stat *st)
1252 return 0; 1256 return 0;
1253} 1257}
1254 1258
1259///////////////////////////////////////////////////////////////////////////
1260// this below is funky avoiding opendir to avoid heap allocations thus
1261// getdents and all the os specific stuff as this is intendedf for use
1262// between fork and exec normally ... this is important
1263#if defined(__FreeBSD__)
1264# define do_getdents(fd, buf, size) getdents(fd, buf, size)
1265typedef struct
1266{
1267 ino_t d_ino;
1268 off_t d_off;
1269 unsigned short d_reclen;
1270 unsigned char d_type;
1271 unsigned char ____pad0;
1272 unsigned short d_namlen;
1273 unsigned short ____pad1;
1274 char d_name[4096];
1275} Dirent;
1276#elif defined(__OpenBSD__)
1277# define do_getdents(fd, buf, size) getdents(fd, buf, size)
1278typedef struct
1279{
1280 __ino_t d_ino;
1281 __off_t d_off;
1282 unsigned short d_reclen;
1283 unsigned char d_type;
1284 unsigned char d_namlen;
1285 unsigned char ____pad[4];
1286 char d_name[4096];
1287} Dirent;
1288#elif defined(__linux__)
1289# define do_getdents(fd, buf, size) getdents64(fd, buf, size)
1290typedef struct
1291{
1292 ino64_t d_ino;
1293 off64_t d_off;
1294 unsigned short d_reclen;
1295 unsigned char d_type;
1296 char d_name[4096];
1297} Dirent;
1298#endif
1299
1255EAPI void 1300EAPI void
1256eina_file_close_from(int fd, int *except_fd) 1301eina_file_close_from(int fd, int *except_fd)
1257{ 1302{
@@ -1259,62 +1304,171 @@ eina_file_close_from(int fd, int *except_fd)
1259 // XXX: what do to here? anything? 1304 // XXX: what do to here? anything?
1260#else 1305#else
1261#ifdef HAVE_DIRENT_H 1306#ifdef HAVE_DIRENT_H
1307//# if 0
1308# if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__)
1309 int dirfd;
1310 Dirent *d;
1311 char buf[4096];
1312 int *closes = NULL;
1313 int num_closes = 0, i, j, clo, num;
1314 const char *fname;
1315 ssize_t pos, ret;
1316 Eina_Bool do_read;
1317
1318 dirfd = open("/proc/self/fd", O_RDONLY | O_DIRECTORY);
1319 if (dirfd < 0) dirfd = open("/dev/fd", O_RDONLY | O_DIRECTORY);
1320 if (dirfd >= 0)
1321 {
1322 // count # of closes - the dir list should/will not change as its
1323 // the fd's we have open so we can read it twice with no changes
1324 // to it
1325 do_read = EINA_TRUE;
1326 for (;;)
1327 {
1328skip:
1329 if (do_read)
1330 {
1331 pos = 0;
1332 ret = do_getdents(dirfd, buf, sizeof(buf));
1333 if (ret <= 0) break;
1334 do_read = EINA_FALSE;
1335 }
1336 d = (Dirent *)(buf + pos);
1337 fname = d->d_name;
1338 pos += d->d_reclen;
1339 if (pos >= ret) do_read = EINA_TRUE;
1340 if (!((fname[0] >= '0') && (fname[0] <= '9'))) continue;
1341 num = atoi(fname);
1342 if (num < fd) continue;
1343 if (except_fd)
1344 {
1345 for (j = 0; except_fd[j] >= 0; j++)
1346 {
1347 if (except_fd[j] == num) goto skip;
1348 }
1349 }
1350 num_closes++;
1351 }
1352 // alloc closes list and walk again to fill it - on stack to avoid
1353 // heap allocs
1354 closes = alloca(num_closes * sizeof(int));
1355 if ((closes) && (num_closes > 0))
1356 {
1357 clo = 0;
1358 lseek(dirfd, 0, SEEK_SET);
1359 do_read = EINA_TRUE;
1360 for (;;)
1361 {
1362skip2:
1363 if (do_read)
1364 {
1365 pos = 0;
1366 ret = do_getdents(dirfd, buf, sizeof(buf));
1367 if (ret <= 0) break;
1368 do_read = EINA_FALSE;
1369 }
1370 d = (Dirent *)(buf + pos);
1371 fname = d->d_name;
1372 pos += d->d_reclen;
1373 if (pos >= ret) do_read = EINA_TRUE;
1374 if (!((fname[0] >= '0') && (fname[0] <= '9'))) continue;
1375 num = atoi(fname);
1376 if (num < fd) continue;
1377 if (except_fd)
1378 {
1379 for (j = 0; except_fd[j] >= 0; j++)
1380 {
1381 if (except_fd[j] == num) goto skip2;
1382 }
1383 }
1384 if (clo < num_closes) closes[clo] = num;
1385 clo++;
1386 }
1387 }
1388 close(dirfd);
1389 // now go close all those fd's - some may be invalide like the dir
1390 // reading fd above... that's ok.
1391 for (i = 0; i < num_closes; i++)
1392 {
1393 close(closes[i]);
1394 }
1395 return;
1396 }
1397# else
1262 DIR *dir; 1398 DIR *dir;
1399 int *closes = NULL;
1400 int num_closes = 0, i, j, clo, num;
1401 struct dirent *dp;
1402 const char *fname;
1263 1403
1264 dir = opendir("/proc/self/fd"); 1404 dir = opendir("/proc/self/fd");
1265 if (!dir) dir = opendir("/dev/fd"); 1405 if (!dir) dir = opendir("/dev/fd");
1266 if (dir) 1406 if (dir)
1267 { 1407 {
1268 struct dirent *dp; 1408 // count # of closes - the dir list should/will not change as its
1269 const char *fname; 1409 // the fd's we have open so we can read it twice with no changes
1270 int *closes = NULL; 1410 // to it
1271 int num_closes = 0, i;
1272
1273 for (;;) 1411 for (;;)
1274 { 1412 {
1275skip: 1413skip:
1276 dp = readdir(dir); 1414 if (!(dp = readdir(dir))) break;
1277 if (!dp) break;
1278 fname = dp->d_name; 1415 fname = dp->d_name;
1279 1416 if (!((fname[0] >= '0') && (fname[0] <= '9'))) continue;
1280 if ((fname[0] >= '0') && (fname[0] <= '9')) 1417 num = atoi(fname);
1418 if (num < fd) continue;
1419 if (except_fd)
1281 { 1420 {
1282 int num = atoi(fname); 1421 for (j = 0; except_fd[j] >= 0; j++)
1283 if (num >= fd)
1284 { 1422 {
1285 if (except_fd) 1423 if (except_fd[j] == num) goto skip;
1286 { 1424 }
1287 int j; 1425 }
1288 1426 num_closes++;
1289 for (j = 0; except_fd[j] >= 0; j++) 1427 }
1290 { 1428 // alloc closes list and walk again to fill it - on stack to avoid
1291 if (except_fd[j] == num) goto skip; 1429 // heap allocs
1292 } 1430 closes = alloca(num_closes * sizeof(int));
1293 } 1431 if ((closes) && (num_closes > 0))
1294 num_closes++; 1432 {
1295 int *tmp = realloc(closes, num_closes * sizeof(int)); 1433 clo = 0;
1296 if (!tmp) num_closes--; 1434 seekdir(dir, 0);
1297 else 1435 for (;;)
1436 {
1437skip2:
1438 if (!(dp = readdir(dir))) break;
1439 fname = dp->d_name;
1440 if (!((fname[0] >= '0') && (fname[0] <= '9'))) continue;
1441 num = atoi(fname);
1442 if (num < fd) continue;
1443 if (except_fd)
1444 {
1445 for (j = 0; except_fd[j] >= 0; j++)
1298 { 1446 {
1299 closes = tmp; 1447 if (except_fd[j] == num) goto skip2;
1300 closes[num_closes - 1] = num;
1301 } 1448 }
1302 } 1449 }
1450 if (clo < num_closes) closes[clo] = num;
1451 clo++;
1303 } 1452 }
1304 } 1453 }
1305 closedir(dir); 1454 closedir(dir);
1306 for (i = 0; i < num_closes; i++) close(closes[i]); 1455 // now go close all those fd's - some may be invalide like the dir
1307 free(closes); 1456 // reading fd above... that's ok.
1457 for (i = 0; i < num_closes; i++)
1458 {
1459 close(closes[i]);
1460 }
1308 return; 1461 return;
1309 } 1462 }
1463# endif
1310#endif 1464#endif
1311 int i, max = 1024; 1465 int max = 1024;
1312 1466
1313# ifdef HAVE_SYS_RESOURCE_H 1467#ifdef HAVE_SYS_RESOURCE_H
1314 struct rlimit lim; 1468 struct rlimit lim;
1315 if (getrlimit(RLIMIT_NOFILE, &lim) < 0) return; 1469 if (getrlimit(RLIMIT_NOFILE, &lim) < 0) return;
1316 max = lim.rlim_max; 1470 max = lim.rlim_max;
1317# endif 1471#endif
1318 for (i = fd; i < max;) 1472 for (i = fd; i < max;)
1319 { 1473 {
1320 if (except_fd) 1474 if (except_fd)
@@ -1323,11 +1477,11 @@ skip:
1323 1477
1324 for (j = 0; except_fd[j] >= 0; j++) 1478 for (j = 0; except_fd[j] >= 0; j++)
1325 { 1479 {
1326 if (except_fd[j] == i) goto skip2; 1480 if (except_fd[j] == i) goto skip3;
1327 } 1481 }
1328 } 1482 }
1329 close(i); 1483 close(i);
1330skip2: 1484skip3:
1331 i++; 1485 i++;
1332 } 1486 }
1333#endif 1487#endif