Commit 1356ecc58fa84d6072c1f3a041b9cd6d905202ea
1 parent
99bf5fea
Make parameter file reading and writing thread safe (#3287)
Showing
4 changed files
with
120 additions
and
107 deletions
ChangeLog
NEWS
| 1 | 1 | New Features and Important Changes in GammaLib 1.7.1 |
| 2 | 2 | |
| 3 | -22 July 2020 | |
| 3 | +29 July 2020 | |
| 4 | 4 | |
| 5 | 5 | |
| 6 | 6 | 1. Introduction |
| ... | ... | @@ -43,7 +43,9 @@ None |
| 43 | 43 | |
| 44 | 44 | 4. Application module |
| 45 | 45 | --------------------- |
| 46 | -None | |
| 46 | +The reading and writing of the parameter file in GApplicationPars::read() | |
| 47 | +and GApplicationPars::write() was put in an OpenMP critical zone to assure | |
| 48 | +that the reading and writing is thread safe (#3287). | |
| 47 | 49 | |
| 48 | 50 | |
| 49 | 51 | 5. Base module | ... | ... |
doc/source/admin/release_history/1.7.1.rst
| 1 | 1 | .. _1.7.1: |
| 2 | 2 | |
| 3 | -GammaLib 1.7.1 release (22 July 2020) | |
| 3 | +GammaLib 1.7.1 release (29 July 2020) | |
| 4 | 4 | ===================================== |
| 5 | 5 | |
| 6 | 6 | Overview |
| ... | ... | @@ -10,6 +10,8 @@ GammaLib 1.7.1 is a bug fix release for GammaLib release 1.7. |
| 10 | 10 | |
| 11 | 11 | The following bugs were fixed: |
| 12 | 12 | |
| 13 | +* [`3287 <https://cta-redmine.irap.omp.eu/issues/3287>`_] - | |
| 14 | + Make parameter file reading and writing thread safe | |
| 13 | 15 | * [`3280 <https://cta-redmine.irap.omp.eu/issues/3280>`_] - |
| 14 | 16 | Add quotes to sky region names |
| 15 | 17 | * [`3279 <https://cta-redmine.irap.omp.eu/issues/3279>`_] - | ... | ... |
src/app/GApplicationPars.cpp
| ... | ... | @@ -1268,62 +1268,66 @@ std::string GApplicationPars::outpath(const std::string& filename) const |
| 1268 | 1268 | ***************************************************************************/ |
| 1269 | 1269 | void GApplicationPars::read(const std::string& filename) |
| 1270 | 1270 | { |
| 1271 | - // Allocate line buffer | |
| 1272 | - const int n = 1000; | |
| 1273 | - char line[n]; | |
| 1274 | - | |
| 1275 | - // Trying to get file lock | |
| 1276 | - #if defined(G_LOCK_PARFILE) | |
| 1277 | - struct flock lock; | |
| 1278 | - lock.l_type = F_RDLCK; // Want a read lock | |
| 1279 | - lock.l_whence = SEEK_SET; // Want beginning of file | |
| 1280 | - lock.l_start = 0; // No offset, lock entire file ... | |
| 1281 | - lock.l_len = 0; // ... to the end | |
| 1282 | - lock.l_pid = getpid(); // Current process ID | |
| 1283 | - int fd; | |
| 1284 | - if ((fd = open(filename.c_str(), O_RDONLY)) == -1) { | |
| 1285 | - throw GException::par_file_open_error(G_READ, filename, | |
| 1286 | - "Could not open file for locking."); | |
| 1287 | - } | |
| 1288 | - #if defined(G_CHECK_LOCK_PARFILE) | |
| 1289 | - if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked | |
| 1290 | - throw GException::par_file_open_error(G_READ, filename, | |
| 1291 | - "Could not get a lock on the file."); | |
| 1292 | - } | |
| 1293 | - #else | |
| 1294 | - fcntl(fd, F_SETLKW, &lock); | |
| 1295 | - #endif | |
| 1296 | - #endif | |
| 1271 | + // Put in OpenMP critical zone | |
| 1272 | + #pragma omp critical(GApplicationsPars_read) | |
| 1273 | + { | |
| 1274 | + // Allocate line buffer | |
| 1275 | + const int n = 1000; | |
| 1276 | + char line[n]; | |
| 1277 | + | |
| 1278 | + // Trying to get file lock | |
| 1279 | + #if defined(G_LOCK_PARFILE) | |
| 1280 | + struct flock lock; | |
| 1281 | + lock.l_type = F_RDLCK; // Want a read lock | |
| 1282 | + lock.l_whence = SEEK_SET; // Want beginning of file | |
| 1283 | + lock.l_start = 0; // No offset, lock entire file ... | |
| 1284 | + lock.l_len = 0; // ... to the end | |
| 1285 | + lock.l_pid = getpid(); // Current process ID | |
| 1286 | + int fd; | |
| 1287 | + if ((fd = open(filename.c_str(), O_RDONLY)) == -1) { | |
| 1288 | + throw GException::par_file_open_error(G_READ, filename, | |
| 1289 | + "Could not open file for locking."); | |
| 1290 | + } | |
| 1291 | + #if defined(G_CHECK_LOCK_PARFILE) | |
| 1292 | + if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked | |
| 1293 | + throw GException::par_file_open_error(G_READ, filename, | |
| 1294 | + "Could not get a lock on the file."); | |
| 1295 | + } | |
| 1296 | + #else | |
| 1297 | + fcntl(fd, F_SETLKW, &lock); | |
| 1298 | + #endif | |
| 1299 | + #endif | |
| 1297 | 1300 | |
| 1298 | - // Open parameter file | |
| 1299 | - FILE* fptr = fopen(filename.c_str(), "r"); | |
| 1300 | - if (fptr == NULL) { | |
| 1301 | - throw GException::par_file_open_error(G_READ, filename); | |
| 1302 | - } | |
| 1301 | + // Open parameter file | |
| 1302 | + FILE* fptr = fopen(filename.c_str(), "r"); | |
| 1303 | + if (fptr == NULL) { | |
| 1304 | + throw GException::par_file_open_error(G_READ, filename); | |
| 1305 | + } | |
| 1303 | 1306 | |
| 1304 | - // Read lines | |
| 1305 | - while (fgets(line, n, fptr) != NULL) { | |
| 1306 | - m_parfile.push_back(std::string(line)); | |
| 1307 | - } | |
| 1307 | + // Read lines | |
| 1308 | + while (fgets(line, n, fptr) != NULL) { | |
| 1309 | + m_parfile.push_back(std::string(line)); | |
| 1310 | + } | |
| 1308 | 1311 | |
| 1309 | - // Close file | |
| 1310 | - fclose(fptr); | |
| 1312 | + // Close file | |
| 1313 | + fclose(fptr); | |
| 1311 | 1314 | |
| 1312 | - // Unlock file | |
| 1313 | - #if defined(G_LOCK_PARFILE) | |
| 1314 | - if (fd != -1) { | |
| 1315 | - lock.l_type = F_UNLCK; | |
| 1316 | - #if defined(G_CHECK_LOCK_PARFILE) | |
| 1317 | - if (fcntl(fd, F_SETLK, &lock) == -1) { | |
| 1318 | - throw GException::par_file_open_error(G_READ, filename, | |
| 1319 | - "Could not unlock the file."); | |
| 1315 | + // Unlock file | |
| 1316 | + #if defined(G_LOCK_PARFILE) | |
| 1317 | + if (fd != -1) { | |
| 1318 | + lock.l_type = F_UNLCK; | |
| 1319 | + #if defined(G_CHECK_LOCK_PARFILE) | |
| 1320 | + if (fcntl(fd, F_SETLK, &lock) == -1) { | |
| 1321 | + throw GException::par_file_open_error(G_READ, filename, | |
| 1322 | + "Could not unlock the file."); | |
| 1323 | + } | |
| 1324 | + #else | |
| 1325 | + fcntl(fd, F_SETLK, &lock); | |
| 1326 | + #endif | |
| 1327 | + close(fd); | |
| 1320 | 1328 | } |
| 1321 | - #else | |
| 1322 | - fcntl(fd, F_SETLK, &lock); | |
| 1323 | 1329 | #endif |
| 1324 | - close(fd); | |
| 1325 | 1330 | } |
| 1326 | - #endif | |
| 1327 | 1331 | |
| 1328 | 1332 | // Return |
| 1329 | 1333 | return; |
| ... | ... | @@ -1343,42 +1347,23 @@ void GApplicationPars::read(const std::string& filename) |
| 1343 | 1347 | ***************************************************************************/ |
| 1344 | 1348 | void GApplicationPars::write(const std::string& filename) const |
| 1345 | 1349 | { |
| 1346 | - // Trying to get file lock. We have to do this after opening the file | |
| 1347 | - // using the fopen function, as the file may not exist, hence it needs | |
| 1348 | - // to be created first. | |
| 1349 | - #if defined(G_LOCK_PARFILE) | |
| 1350 | - struct flock lock; | |
| 1351 | - lock.l_type = F_WRLCK; // Want a write lock | |
| 1352 | - lock.l_whence = SEEK_SET; // Want beginning of file | |
| 1353 | - lock.l_start = 0; // No offset, lock entire file ... | |
| 1354 | - lock.l_len = 0; // ... to the end | |
| 1355 | - lock.l_pid = getpid(); // Current process ID | |
| 1356 | - int fd; | |
| 1357 | - if ((fd = open(filename.c_str(), O_WRONLY)) != -1) { | |
| 1358 | - #if defined(G_CHECK_LOCK_PARFILE) | |
| 1359 | - if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked | |
| 1360 | - throw GException::par_file_open_error(G_WRITE, filename, | |
| 1361 | - "Could not get a lock on the file."); | |
| 1362 | - } | |
| 1363 | - #else | |
| 1364 | - fcntl(fd, F_SETLKW, &lock); | |
| 1365 | - #endif | |
| 1366 | - } | |
| 1367 | - #endif | |
| 1368 | - | |
| 1369 | - // Open parameter file. | |
| 1370 | - FILE* fptr = fopen(filename.c_str(), "w"); | |
| 1371 | - if (fptr == NULL) { | |
| 1372 | - throw GException::par_file_open_error(G_WRITE, filename); | |
| 1373 | - } | |
| 1374 | - | |
| 1375 | - // If file is not locked then lock it now. | |
| 1376 | - #if defined(G_LOCK_PARFILE) | |
| 1377 | - if (fd == -1) { | |
| 1350 | + // Put in OpenMP critical zone | |
| 1351 | + #pragma omp critical(GApplicationsPars_write) | |
| 1352 | + { | |
| 1353 | + // Trying to get file lock. We have to do this after opening the file | |
| 1354 | + // using the fopen function, as the file may not exist, hence it needs | |
| 1355 | + // to be created first. | |
| 1356 | + #if defined(G_LOCK_PARFILE) | |
| 1357 | + struct flock lock; | |
| 1358 | + lock.l_type = F_WRLCK; // Want a write lock | |
| 1359 | + lock.l_whence = SEEK_SET; // Want beginning of file | |
| 1360 | + lock.l_start = 0; // No offset, lock entire file ... | |
| 1361 | + lock.l_len = 0; // ... to the end | |
| 1362 | + lock.l_pid = getpid(); // Current process ID | |
| 1363 | + int fd; | |
| 1378 | 1364 | if ((fd = open(filename.c_str(), O_WRONLY)) != -1) { |
| 1379 | 1365 | #if defined(G_CHECK_LOCK_PARFILE) |
| 1380 | 1366 | if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked |
| 1381 | - fclose(fptr); | |
| 1382 | 1367 | throw GException::par_file_open_error(G_WRITE, filename, |
| 1383 | 1368 | "Could not get a lock on the file."); |
| 1384 | 1369 | } |
| ... | ... | @@ -1386,33 +1371,56 @@ void GApplicationPars::write(const std::string& filename) const |
| 1386 | 1371 | fcntl(fd, F_SETLKW, &lock); |
| 1387 | 1372 | #endif |
| 1388 | 1373 | } |
| 1389 | - } | |
| 1390 | - #endif | |
| 1374 | + #endif | |
| 1391 | 1375 | |
| 1392 | - // Write lines | |
| 1393 | - for (int i = 0; i < m_parfile.size(); ++i) { | |
| 1394 | - fprintf(fptr, "%s", m_parfile[i].c_str()); | |
| 1395 | - } | |
| 1376 | + // Open parameter file. | |
| 1377 | + FILE* fptr = fopen(filename.c_str(), "w"); | |
| 1378 | + if (fptr == NULL) { | |
| 1379 | + throw GException::par_file_open_error(G_WRITE, filename); | |
| 1380 | + } | |
| 1396 | 1381 | |
| 1397 | - // Close file | |
| 1398 | - fclose(fptr); | |
| 1382 | + // If file is not locked then lock it now. | |
| 1383 | + #if defined(G_LOCK_PARFILE) | |
| 1384 | + if (fd == -1) { | |
| 1385 | + if ((fd = open(filename.c_str(), O_WRONLY)) != -1) { | |
| 1386 | + #if defined(G_CHECK_LOCK_PARFILE) | |
| 1387 | + if (fcntl(fd, F_SETLKW, &lock) == -1) { // F_SETLKW: wait until unlocked | |
| 1388 | + fclose(fptr); | |
| 1389 | + throw GException::par_file_open_error(G_WRITE, filename, | |
| 1390 | + "Could not get a lock on the file."); | |
| 1391 | + } | |
| 1392 | + #else | |
| 1393 | + fcntl(fd, F_SETLKW, &lock); | |
| 1394 | + #endif | |
| 1395 | + } | |
| 1396 | + } | |
| 1397 | + #endif | |
| 1399 | 1398 | |
| 1400 | - // Unlock file | |
| 1401 | - #if defined(G_LOCK_PARFILE) | |
| 1402 | - if (fd != -1) { | |
| 1403 | - lock.l_type = F_UNLCK; | |
| 1404 | - #if defined(G_CHECK_LOCK_PARFILE) | |
| 1405 | - if (fcntl(fd, F_SETLK, &lock) == -1) { | |
| 1406 | - throw GException::par_file_open_error(G_WRITE, filename, | |
| 1407 | - "Could not unlock the file."); | |
| 1399 | + // Write lines | |
| 1400 | + for (int i = 0; i < m_parfile.size(); ++i) { | |
| 1401 | + fprintf(fptr, "%s", m_parfile[i].c_str()); | |
| 1402 | + } | |
| 1403 | + | |
| 1404 | + // Close file | |
| 1405 | + fclose(fptr); | |
| 1406 | + | |
| 1407 | + // Unlock file | |
| 1408 | + #if defined(G_LOCK_PARFILE) | |
| 1409 | + if (fd != -1) { | |
| 1410 | + lock.l_type = F_UNLCK; | |
| 1411 | + #if defined(G_CHECK_LOCK_PARFILE) | |
| 1412 | + if (fcntl(fd, F_SETLK, &lock) == -1) { | |
| 1413 | + throw GException::par_file_open_error(G_WRITE, filename, | |
| 1414 | + "Could not unlock the file."); | |
| 1415 | + } | |
| 1416 | + #else | |
| 1417 | + fcntl(fd, F_SETLK, &lock); | |
| 1418 | + #endif | |
| 1419 | + close(fd); | |
| 1408 | 1420 | } |
| 1409 | - #else | |
| 1410 | - fcntl(fd, F_SETLK, &lock); | |
| 1411 | 1421 | #endif |
| 1412 | - close(fd); | |
| 1413 | 1422 | } |
| 1414 | - #endif | |
| 1415 | - | |
| 1423 | + | |
| 1416 | 1424 | // Return |
| 1417 | 1425 | return; |
| 1418 | 1426 | } | ... | ... |