1212#include " group.h"
1313#include " net.h"
1414#include " p2p.h"
15+ #include " reg_pool.h"
1516#include " topo.h"
1617#include " transport.h"
1718#include " type.h"
@@ -294,8 +295,19 @@ static flagcxResult_t flagcxCommInitRankFunc(struct flagcxAsyncJob *job_) {
294295 int nranks = comm->nRanks ;
295296 for (int i = 0 ; i < MAXCHANNELS ; i++) {
296297 FLAGCXCHECK (flagcxCalloc (&comm->channels [i].peers , nranks));
297- for (int r = 0 ; r < nranks; r++)
298+ for (int r = 0 ; r < nranks; r++) {
298299 FLAGCXCHECK (flagcxCalloc (&comm->channels [i].peers [r], nranks));
300+ }
301+ }
302+ // Set tpRank = comm->rank for all channel connectors so local RPCs
303+ // route through peerSocks[myRank] to the local service thread
304+ for (int i = 0 ; i < MAXCHANNELS ; i++) {
305+ for (int r = 0 ; r < nranks; r++) {
306+ for (int c = 0 ; c < FLAGCX_MAX_CONNS ; c++) {
307+ comm->channels [i].peers [r]->send [c].proxyConn .tpRank = comm->rank ;
308+ comm->channels [i].peers [r]->recv [c].proxyConn .tpRank = comm->rank ;
309+ }
310+ }
299311 }
300312 FLAGCXCHECK (flagcxCalloc (&comm->connectSend , nranks));
301313 FLAGCXCHECK (flagcxCalloc (&comm->connectRecv , nranks));
@@ -339,6 +351,33 @@ static flagcxResult_t flagcxCommInitRankFunc(struct flagcxAsyncJob *job_) {
339351 INFO (FLAGCX_INIT , " Flagcx RuntimeProxy flag set to %d" , runtimeProxy);
340352 if (!runtimeProxy) {
341353 FLAGCXCHECK (flagcxProxyInit (comm));
354+
355+ // Allocate gproxyConn array and populate peerAddresses for peer proxy
356+ // connections
357+ FLAGCXCHECK (flagcxCalloc (&comm->gproxyConn , comm->nRanks ));
358+ FLAGCXCHECK (flagcxCalloc (&comm->proxyState ->peerAddresses , comm->nRanks ));
359+ comm->proxyState ->peerAddresses [comm->rank ] =
360+ comm->proxyState ->listenSock .addr ;
361+ FLAGCXCHECK (bootstrapAllGather (comm->bootstrap ,
362+ comm->proxyState ->peerAddresses ,
363+ sizeof (union flagcxSocketAddress)));
364+
365+ // Pre-connect all peer sockets (including self)
366+ FLAGCXCHECK (flagcxCalloc (&comm->proxyState ->peerSocks , comm->nRanks ));
367+ comm->proxyState ->nPeerSocks = comm->nRanks ;
368+ for (int i = 0 ; i < comm->nRanks ; i++) {
369+ FLAGCXCHECK (flagcxSocketSetFd (-1 , &comm->proxyState ->peerSocks [i]));
370+ }
371+ for (int i = 0 ; i < comm->nRanks ; i++) {
372+ struct flagcxSocket *sock = &comm->proxyState ->peerSocks [i];
373+ FLAGCXCHECK (flagcxSocketInit (sock, comm->proxyState ->peerAddresses + i,
374+ comm->magic , flagcxSocketTypeProxy));
375+ FLAGCXCHECK (flagcxSocketConnect (sock));
376+ int ready = 0 ;
377+ while (!ready) {
378+ FLAGCXCHECK (flagcxSocketReady (sock, &ready));
379+ }
380+ }
342381 }
343382 }
344383
@@ -461,6 +500,8 @@ flagcxResult_t flagcxHeteroCommUserRank(const flagcxHeteroComm_t comm,
461500
462501flagcxResult_t flagcxHeteroCommDestroy (flagcxHeteroComm_t comm) {
463502 FLAGCXCHECK (flagcxHeteroRmaProxyStop (comm));
503+ // Clean up P2P IPC handles while proxy is still alive and peerSocks valid
504+ FLAGCXCHECK (globalRegPool.removeAllP2pHandles (comm));
464505 flagcxProxyDestroy (comm);
465506 for (int i = 0 ; i < MAXCHANNELS ; i++) {
466507 for (int r = 0 ; r < comm->nRanks ; r++) {
@@ -477,6 +518,19 @@ flagcxResult_t flagcxHeteroCommDestroy(flagcxHeteroComm_t comm) {
477518
478519 free (comm->connectSend );
479520 free (comm->connectRecv );
521+ if (comm->gproxyConn ) {
522+ // gproxyConn[i].connection is an opaque handle pointing to a
523+ // flagcxProxyConnection allocated and owned by the peer's service thread.
524+ // Do NOT free it here — the peer frees it when its service thread exits.
525+ free (comm->gproxyConn );
526+ }
527+ free (comm->proxyState ->peerAddresses );
528+ if (comm->proxyState ->peerSocks != NULL ) {
529+ for (int i = 0 ; i < comm->proxyState ->nPeerSocks ; i++) {
530+ flagcxSocketClose (&comm->proxyState ->peerSocks [i]);
531+ }
532+ free (comm->proxyState ->peerSocks );
533+ }
480534 free (comm->proxyState );
481535 free (comm->tasks .peers );
482536 free (comm->tasks .p2pOrder );
0 commit comments