Skip to content

Commit 92d4f2b

Browse files
author
abacus_fixer
committed
fix(socket_handlers): keep POSDATA state check on the shared quit path
handle_posdata performed the READY-state check with a root-only quit_if_root_failed call before read_posdata, while non-root ranks fell through to read_posdata's own quit_if_root_failed. The two paths matched only because each issued exactly one bcast_int plus one bcast_string; any collective added ahead of read_posdata's quit would deadlock non-root ranks after the root quit. Pass DriverState into read_posdata and set io_failed there so all ranks pass through the single quit_if_root_failed sequence, matching the other socket handlers.
1 parent 1f58fce commit 92d4f2b

1 file changed

Lines changed: 50 additions & 42 deletions

File tree

source/source_relax/socket_handlers.cpp

Lines changed: 50 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -172,55 +172,67 @@ struct PosdataPayload
172172

173173
// Root rank reads and validates the POSDATA frame; the results are then
174174
// broadcast to all ranks. Calls WARNING_QUIT on protocol/validation failure.
175-
PosdataPayload read_posdata(IpiSocket& socket, const UnitCell& ucell)
175+
// The READY-state check must stay inside this function so that every rank
176+
// passes through the single quit_if_root_failed collective sequence below;
177+
// a root-only early quit outside would deadlock if any collective were
178+
// added ahead of it.
179+
PosdataPayload read_posdata(IpiSocket& socket, const UnitCell& ucell, const DriverState state)
176180
{
177181
PosdataPayload payload;
178182
int io_failed = 0;
179183
std::string io_message;
180184
if (is_root())
181185
{
182-
try
186+
if (state != DriverState::Ready)
183187
{
184-
const std::vector<double> cell_values = socket.read_doubles(9);
185-
const std::vector<double> inverse_values = socket.read_doubles(9);
186-
std::copy(cell_values.begin(), cell_values.end(), payload.cell.begin());
187-
std::copy(inverse_values.begin(), inverse_values.end(), payload.inv_cell.begin());
188-
payload.nat_socket = socket.read_int32();
189-
const SocketFrame::CellValidation validation
190-
= SocketFrame::validate_ipi_cell(payload.cell,
191-
payload.inv_cell,
192-
kMaxCellCondition,
193-
kInverseAbsoluteTolerance,
194-
kInverseRelativeTolerance);
195-
if (!validation.ok)
196-
{
197-
io_failed = 1;
198-
io_message = "invalid POSDATA cell: " + validation.message;
199-
}
200-
std::size_t coordinate_count = 0;
201-
if (io_failed == 0
202-
&& !SocketFrame::checked_position_count(payload.nat_socket,
203-
ucell.nat,
204-
coordinate_count,
205-
io_message))
206-
{
207-
io_failed = 1;
208-
}
209-
if (io_failed == 0)
188+
io_failed = 1;
189+
io_message = "POSDATA requires READY state";
190+
}
191+
else
192+
{
193+
try
210194
{
211-
payload.positions = socket.read_doubles(coordinate_count);
212-
if (!SocketFrame::validate_positions(payload.positions,
213-
coordinate_count,
214-
io_message))
195+
const std::vector<double> cell_values = socket.read_doubles(9);
196+
const std::vector<double> inverse_values = socket.read_doubles(9);
197+
std::copy(cell_values.begin(), cell_values.end(), payload.cell.begin());
198+
std::copy(inverse_values.begin(), inverse_values.end(), payload.inv_cell.begin());
199+
payload.nat_socket = socket.read_int32();
200+
const SocketFrame::CellValidation validation
201+
= SocketFrame::validate_ipi_cell(payload.cell,
202+
payload.inv_cell,
203+
kMaxCellCondition,
204+
kInverseAbsoluteTolerance,
205+
kInverseRelativeTolerance);
206+
if (!validation.ok)
207+
{
208+
io_failed = 1;
209+
io_message = "invalid POSDATA cell: " + validation.message;
210+
}
211+
std::size_t coordinate_count = 0;
212+
if (io_failed == 0
213+
&& !SocketFrame::checked_position_count(payload.nat_socket,
214+
ucell.nat,
215+
coordinate_count,
216+
io_message))
215217
{
216218
io_failed = 1;
217219
}
220+
if (io_failed == 0)
221+
{
222+
payload.positions = socket.read_doubles(coordinate_count);
223+
if (!SocketFrame::validate_positions(payload.positions,
224+
coordinate_count,
225+
io_message))
226+
{
227+
io_failed = 1;
228+
}
229+
}
230+
}
231+
catch (const std::exception& exc)
232+
{
233+
io_failed = 1;
234+
io_message = exc.what();
218235
}
219-
}
220-
catch (const std::exception& exc)
221-
{
222-
io_failed = 1;
223-
io_message = exc.what();
224236
}
225237
}
226238
quit_if_root_failed(io_failed, io_message);
@@ -428,11 +440,7 @@ void handle_posdata(IpiSocket& socket,
428440
DriverContext& context,
429441
std::ofstream& ofs_running)
430442
{
431-
if (is_root() && context.state != DriverState::Ready)
432-
{
433-
quit_if_root_failed(1, "POSDATA requires READY state");
434-
}
435-
PosdataPayload payload = read_posdata(socket, *context.ucell);
443+
PosdataPayload payload = read_posdata(socket, *context.ucell, context.state);
436444
bcast_posdata(payload);
437445
check_posdata_geometry(context, payload, context);
438446
run_esolver_for_positions(*context.ucell, context.esolver, payload.positions, context.istep);

0 commit comments

Comments
 (0)