@@ -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