From d08fc47192601a352e6b6151163aba2228c16aaa Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Fri, 15 Aug 2025 17:42:04 +0200 Subject: [PATCH 1/7] ENH: Allow driver clients to poll for input Closes gh-1144 --- src/util/util_talker.c | 106 ++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 38 deletions(-) diff --git a/src/util/util_talker.c b/src/util/util_talker.c index b7bd265ec9..bcfd165c41 100644 --- a/src/util/util_talker.c +++ b/src/util/util_talker.c @@ -20,63 +20,93 @@ void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * perror("util_talker: not coded for this architecture"); exit(1); #else - int sock = 0, valread; - int na = ((int) *n1); + int sock = 0; + const int max_retries = 30; + const int retry_delay_seconds = 2; + int retries = 0; - addr_name[na] = 0; - addr_name[na+1] = 0; - - if (*inet>0) + if (*inet > 0) { - struct sockaddr_in serv_addr; + // --- TCP/IP Socket Logic --- + struct sockaddr_in serv_addr; int port = ((int) *portin); + int na = ((int) *n1); + char addr_name_buf[256]; // Use a safe buffer + strncpy(addr_name_buf, addr_name, na); + addr_name_buf[na] = '\0'; - printf("util_talker: addr_name=%s\n",addr_name); - printf("util_talker: port=%d\n",port); + printf("util_talker: Attempting to connect to TCP server %s:%d\n", addr_name_buf, port); - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) - { - printf("\nutil_talker:Socket creation error \n"); + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + perror("util_talker: TCP socket creation error"); exit(1); - } - serv_addr.sin_family = AF_INET; - serv_addr.sin_port = htons(port); + } + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(port); - // Convert IPv4 and IPv6 addresses from text to binary form - if(inet_pton(AF_INET, addr_name, &serv_addr.sin_addr)<=0) - { - printf("\nutil_talker:Invalid address/ Address not supported \n"); + if(inet_pton(AF_INET, addr_name_buf, &serv_addr.sin_addr) <= 0) + { + printf("\nutil_talker: Invalid address/Address not supported\n"); exit(1); - } - if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - { - printf("\nutil_talker:Connection Failed \n"); - exit(1); - } + } + + // --- Retry Loop for TCP --- + while (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + if (++retries >= max_retries) { + fprintf(stderr, "\nutil_talker: TCP connection failed after %d attempts: %s. Exiting.\n", max_retries, strerror(errno)); + exit(1); + } + printf("util_talker: Connection failed. Retrying in %d seconds... (%d/%d)\n", + retry_delay_seconds, retries, max_retries); + sleep(retry_delay_seconds); + } } else { + // --- UNIX Domain Socket Logic --- struct sockaddr_un serv_addr; + int na = ((int)*n1); + char addr_name_buf[256]; + strncpy(addr_name_buf, addr_name, na); + addr_name_buf[na] = '\0'; + memset(&serv_addr, 0, sizeof(struct sockaddr_un)); serv_addr.sun_family = AF_UNIX; - strcpy(serv_addr.sun_path, "/tmp/ipi_"); - strcpy(serv_addr.sun_path+9, addr_name); - if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - { - printf("\nutil_talker:Socket creation error \n"); + // Construct the full socket path, same as the server + snprintf(serv_addr.sun_path, sizeof(serv_addr.sun_path), "/tmp/ipi_%s", + addr_name_buf); + + printf("util_talker: Attempting to connect to UNIX socket %s\n", + serv_addr.sun_path); + + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + perror("util_talker: UNIX socket creation error"); exit(1); } - if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) - { - printf("\nutil_talker:Failed to connect to UNIX socket \n"); - exit(1); + + // --- Retry Loop for UNIX --- + while (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < + 0) { + if (++retries >= max_retries) { + fprintf(stderr, + "\nutil_talker: UNIX socket connection failed after %d " + "attempts: %s. Exiting.\n", + max_retries, strerror(errno)); + exit(1); + } + printf("util_talker: Connection failed. Retrying in %d seconds... " + "(%d/%d)\n", + retry_delay_seconds, retries, max_retries); + sleep(retry_delay_seconds); } } - printf("util_talker: sockid=%d\n",sock); - *sockout = ((Integer) sock); -#endif -} + printf("util_talker: Connection successful! Socket ID: %d\n", sock); + *sockout = ((Integer)sock); + #endif + } From bce1e8cf3d8f9fd8f3d0c5109d1e66ac77a736c9 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 16 Aug 2025 01:45:27 +0200 Subject: [PATCH 2/7] MAINT: Validation and error messages for sockets --- src/driver/socket_driver.F | 7 ++++++- src/util/util_talker.c | 21 +++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/driver/socket_driver.F b/src/driver/socket_driver.F index 01d865d938..362779ae86 100644 --- a/src/driver/socket_driver.F +++ b/src/driver/socket_driver.F @@ -25,6 +25,8 @@ integer rion(2),fion(2),nion,nion0 real*8 unita(3,3),invunita(3,3),stress(3,3),energy real*8 cpu1,cpu2 + real*8 retry_delay_seconds + integer max_retries * **** external functions **** logical task_gradient @@ -106,7 +108,10 @@ write(luout,'(" Connected to = ",A)') socket_ip write(luout,'(" Number of atoms =",I8)') nion write(luout,*) - call util_talker(ip,inet,ii-1,port,sock) + retry_delay_seconds = 2.0 + max_retries = 30 + call util_talker(ip,inet,ii-1,port,sock,max_retries, + > retry_delay_seconds) write(luout,*) !call nwpw_talker("127.0.0.1",9,port,sock) end if diff --git a/src/util/util_talker.c b/src/util/util_talker.c index bcfd165c41..2ef4b466f6 100644 --- a/src/util/util_talker.c +++ b/src/util/util_talker.c @@ -14,17 +14,27 @@ #endif #include "typesf2c.h" -void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * portin, Integer * sockout) +void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * portin, Integer * sockout, Integer * max_retries_in, Integer * retry_delay_seconds_in) { #if defined(__MINGW32__) perror("util_talker: not coded for this architecture"); exit(1); #else int sock = 0; - const int max_retries = 30; - const int retry_delay_seconds = 2; + int max_retries = ((int) *max_retries_in); + int retry_delay_seconds = ((int) *retry_delay_seconds_in); int retries = 0; + if (max_retries <= 0){ + perror("Got an invalid (<=0) number of retries, resetting to 30\n"); + max_retries = 30; + } + if (retry_delay_seconds <= 0){ + perror("Got an invalid (<=0) delay for retries, resetting to 2\n"); + retry_delay_seconds = 2; + } + + if (*inet > 0) { // --- TCP/IP Socket Logic --- @@ -58,7 +68,7 @@ void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * fprintf(stderr, "\nutil_talker: TCP connection failed after %d attempts: %s. Exiting.\n", max_retries, strerror(errno)); exit(1); } - printf("util_talker: Connection failed. Retrying in %d seconds... (%d/%d)\n", + printf("util_talker: Connection failed. Retrying in %d second(s)... (%d/%d)\n", retry_delay_seconds, retries, max_retries); sleep(retry_delay_seconds); } @@ -96,8 +106,7 @@ void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * max_retries, strerror(errno)); exit(1); } - printf("util_talker: Connection failed. Retrying in %d seconds... " - "(%d/%d)\n", + printf("util_talker: Connection failed. Retrying in %d second(s)... (%d/%d)\n", retry_delay_seconds, retries, max_retries); sleep(retry_delay_seconds); } From 859caaaad5b90e633555e8a57dbe3ac24d458ade Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 16 Aug 2025 03:07:53 +0200 Subject: [PATCH 3/7] MAINT: Add retries and delay to parameters but these are now required... which isn't great --- src/driver/driver_input.F | 19 ++++++++++++++++++- src/driver/socket_driver.F | 14 ++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/driver/driver_input.F b/src/driver/driver_input.F index 5bc3e2bd8b..3a47cc333e 100644 --- a/src/driver/driver_input.F +++ b/src/driver/driver_input.F @@ -29,6 +29,7 @@ c double precision ascale, bscale, tscale, hscale logical ignore,diagh integer mh,ind + integer max_retries,retry_delay * **** external functions **** logical driver_parse_boolean @@ -98,7 +99,7 @@ c $ mt_log,1,diagh)) $ call errquit('driver_input: rtdb put failed',0, RTDB_ERR) c -c socket ipi_client ip:port +c socket ipi_client ip:port retries delay c else if (inp_compare(.false.,'socket', field)) then if (inp_a(f2)) then @@ -114,6 +115,22 @@ c > ipname(1:ind))) > call errquit('driver_input: rtdb put failed',8,RTDB_ERR) end if + + if (.not. inp_i(max_retries)) call errquit( + & 'driver_input: failed to read retries integer', 0, + & INPUT_ERR) + if (.not. inp_i(retry_delay)) call errquit( + & 'driver_input: failed to read delay float', 0, + & INPUT_ERR) + + if (.not. rtdb_put(rtdb,'driver:socket_retries',mt_int,1, + & max_retries)) call errquit( + & 'driver_input: rtdb put failed', 10, RTDB_ERR) + + if (.not. rtdb_put(rtdb,'driver:socket_delay',mt_int,1, + & retry_delay)) call errquit( + & 'driver_input: rtdb put failed', 11, RTDB_ERR) + diagh = .true. if (.not. rtdb_put(rtdb,'driver:socket', $ mt_log,1,diagh)) diff --git a/src/driver/socket_driver.F b/src/driver/socket_driver.F index 362779ae86..a46f131a4a 100644 --- a/src/driver/socket_driver.F +++ b/src/driver/socket_driver.F @@ -25,8 +25,7 @@ integer rion(2),fion(2),nion,nion0 real*8 unita(3,3),invunita(3,3),stress(3,3),energy real*8 cpu1,cpu2 - real*8 retry_delay_seconds - integer max_retries + integer max_retries, retry_delay_seconds * **** external functions **** logical task_gradient @@ -102,14 +101,21 @@ statebuffer(1:13) = "READY " + if (.not. rtdb_get(rtdb, 'driver:socket_retries', mt_int, 1, + > max_retries)) then + max_retries = 30 + end if + if (.not. rtdb_get(rtdb, 'driver:socket_delay', mt_int, 1, + > retry_delay_seconds)) then + retry_delay_seconds = 2 + end if + if (taskid.eq.MASTER) then write(luout,*) write(luout,*) "== i-PI Socket Client Driver ==" write(luout,'(" Connected to = ",A)') socket_ip write(luout,'(" Number of atoms =",I8)') nion write(luout,*) - retry_delay_seconds = 2.0 - max_retries = 30 call util_talker(ip,inet,ii-1,port,sock,max_retries, > retry_delay_seconds) write(luout,*) From 0d85d258219e7005a400336628fe3a4c6512accc Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 16 Aug 2025 03:35:26 +0200 Subject: [PATCH 4/7] MAINT: Add optional retries and delay for sockets --- src/driver/driver_input.F | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/driver/driver_input.F b/src/driver/driver_input.F index 3a47cc333e..b4b89d66e5 100644 --- a/src/driver/driver_input.F +++ b/src/driver/driver_input.F @@ -99,7 +99,7 @@ c $ mt_log,1,diagh)) $ call errquit('driver_input: rtdb put failed',0, RTDB_ERR) c -c socket ipi_client ip:port retries delay +c socket ipi_client ip:port [retries ] [delay ] c else if (inp_compare(.false.,'socket', field)) then if (inp_a(f2)) then @@ -116,12 +116,20 @@ c > call errquit('driver_input: rtdb put failed',8,RTDB_ERR) end if - if (.not. inp_i(max_retries)) call errquit( - & 'driver_input: failed to read retries integer', 0, - & INPUT_ERR) - if (.not. inp_i(retry_delay)) call errquit( - & 'driver_input: failed to read delay float', 0, - & INPUT_ERR) + max_retries = 30 + retry_delay = 2 + + do while (inp_a(field)) + if (inp_compare(.false., 'retries', field)) then + if (.not. inp_i(max_retries)) call errquit( + & 'driver_input: expected integer for retries', 0, + & INPUT_ERR) + else if (inp_compare(.false., 'delay', field)) then + if (.not. inp_i(retry_delay)) call errquit( + & 'driver_input: expected float for delay',0, + & INPUT_ERR) + end if + end do if (.not. rtdb_put(rtdb,'driver:socket_retries',mt_int,1, & max_retries)) call errquit( From f834157cd1ab3357be26f72b159ca74756d03994 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 16 Aug 2025 03:50:35 +0200 Subject: [PATCH 5/7] MAINT: Palm off retries and delay for later --- src/driver/driver_input.F | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/driver/driver_input.F b/src/driver/driver_input.F index b4b89d66e5..702503198c 100644 --- a/src/driver/driver_input.F +++ b/src/driver/driver_input.F @@ -116,29 +116,24 @@ c > call errquit('driver_input: rtdb put failed',8,RTDB_ERR) end if - max_retries = 30 - retry_delay = 2 - do while (inp_a(field)) - if (inp_compare(.false., 'retries', field)) then + if (inp_compare(.false.,'retries',field)) then if (.not. inp_i(max_retries)) call errquit( - & 'driver_input: expected integer for retries', 0, - & INPUT_ERR) - else if (inp_compare(.false., 'delay', field)) then + & 'driver_input: expected integer for retries',0, + & INPUT_ERR) + if (.not. rtdb_put(rtdb,'driver:socket_retries', + & mt_int,1,max_retries)) call errquit( + & 'driver_input: rtdb put failed',10,RTDB_ERR) + else if (inp_compare(.false.,'delay',field)) then if (.not. inp_i(retry_delay)) call errquit( - & 'driver_input: expected float for delay',0, - & INPUT_ERR) + & 'driver_input: expected int for delay',0, + & INPUT_ERR) + if (.not. rtdb_put(rtdb,'driver:socket_delay', + & mt_int,1,retry_delay)) call errquit( + & 'driver_input: rtdb put failed',11,RTDB_ERR) end if end do - if (.not. rtdb_put(rtdb,'driver:socket_retries',mt_int,1, - & max_retries)) call errquit( - & 'driver_input: rtdb put failed', 10, RTDB_ERR) - - if (.not. rtdb_put(rtdb,'driver:socket_delay',mt_int,1, - & retry_delay)) call errquit( - & 'driver_input: rtdb put failed', 11, RTDB_ERR) - diagh = .true. if (.not. rtdb_put(rtdb,'driver:socket', $ mt_log,1,diagh)) From 56f8ed01a5d412d29e93813ef0e0bb330aa35358 Mon Sep 17 00:00:00 2001 From: Rohit Goswami Date: Sat, 16 Aug 2025 04:00:07 +0200 Subject: [PATCH 6/7] MAINT: Restructure for clearer parameters --- src/driver/driver_input.F | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/driver/driver_input.F b/src/driver/driver_input.F index 702503198c..538563cc2e 100644 --- a/src/driver/driver_input.F +++ b/src/driver/driver_input.F @@ -116,24 +116,6 @@ c > call errquit('driver_input: rtdb put failed',8,RTDB_ERR) end if - do while (inp_a(field)) - if (inp_compare(.false.,'retries',field)) then - if (.not. inp_i(max_retries)) call errquit( - & 'driver_input: expected integer for retries',0, - & INPUT_ERR) - if (.not. rtdb_put(rtdb,'driver:socket_retries', - & mt_int,1,max_retries)) call errquit( - & 'driver_input: rtdb put failed',10,RTDB_ERR) - else if (inp_compare(.false.,'delay',field)) then - if (.not. inp_i(retry_delay)) call errquit( - & 'driver_input: expected int for delay',0, - & INPUT_ERR) - if (.not. rtdb_put(rtdb,'driver:socket_delay', - & mt_int,1,retry_delay)) call errquit( - & 'driver_input: rtdb put failed',11,RTDB_ERR) - end if - end do - diagh = .true. if (.not. rtdb_put(rtdb,'driver:socket', $ mt_log,1,diagh)) @@ -147,7 +129,24 @@ c $ mt_log,1,diagh)) $ call errquit('driver_input: rtdb put failed',0, RTDB_ERR) end if - end if + do while (inp_a(field)) + if (inp_compare(.false.,'retries',field)) then + if (.not. inp_i(max_retries)) call errquit( + & 'driver_input: expected integer for retries',0, + & INPUT_ERR) + if (.not. rtdb_put(rtdb,'driver:socket_retries', + & mt_int,1,max_retries)) call errquit( + & 'driver_input: rtdb put failed',10,RTDB_ERR) + else if (inp_compare(.false.,'delay',field)) then + if (.not. inp_i(retry_delay)) call errquit( + & 'driver_input: expected int for delay',0, + & INPUT_ERR) + if (.not. rtdb_put(rtdb,'driver:socket_delay', + & mt_int,1,retry_delay)) call errquit( + & 'driver_input: rtdb put failed',11,RTDB_ERR) + end if + end do + end if c else if (inp_compare(.false.,'deloc', field)) then if (.not. rtdb_put(rtdb,'driver:deloc',mt_log,1,.true.)) From 3bd78faabe64976c1daab828af9f54d22965bf38 Mon Sep 17 00:00:00 2001 From: edoapra Date: Mon, 18 Aug 2025 17:18:45 -0700 Subject: [PATCH 7/7] formatting --- src/util/util_talker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/util_talker.c b/src/util/util_talker.c index 2ef4b466f6..fcea864273 100644 --- a/src/util/util_talker.c +++ b/src/util/util_talker.c @@ -114,8 +114,8 @@ void FATR util_talker_(char addr_name[], Integer * inet, Integer * n1, Integer * printf("util_talker: Connection successful! Socket ID: %d\n", sock); *sockout = ((Integer)sock); - #endif - } +#endif +}