|
42 | 42 | #include "llvm/Support/TargetSelect.h"
|
43 | 43 | #include "llvm/Support/Timer.h"
|
44 | 44 |
|
| 45 | +#include <cstring> |
45 | 46 | #include <list>
|
46 | 47 | #include <string>
|
47 | 48 |
|
@@ -668,73 +669,82 @@ LLVMJITLinkRemoteTargetProcessControl::LaunchExecutor() {
|
668 | 669 | #endif
|
669 | 670 | }
|
670 | 671 |
|
671 |
| -Expected<std::unique_ptr<TargetProcessControl>> |
672 |
| -LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor() { |
673 |
| -#ifndef LLVM_ON_UNIX |
674 |
| - // FIXME: Add TCP support for Windows. |
675 |
| - return make_error<StringError>("-" + OutOfProcessExecutorConnect.ArgStr + |
676 |
| - " not supported on non-unix platforms", |
677 |
| - inconvertibleErrorCode()); |
678 |
| -#else |
679 |
| - |
680 |
| - shared::registerStringError<LLVMJITLinkChannel>(); |
681 |
| - |
682 |
| - StringRef HostNameStr, PortStr; |
683 |
| - std::tie(HostNameStr, PortStr) = |
684 |
| - StringRef(OutOfProcessExecutorConnect).split(':'); |
685 |
| - |
686 |
| - if (HostNameStr.empty()) |
687 |
| - return make_error<StringError>("host name for -" + |
688 |
| - OutOfProcessExecutorConnect.ArgStr + |
689 |
| - " can not be empty", |
690 |
| - inconvertibleErrorCode()); |
691 |
| - if (PortStr.empty()) |
692 |
| - return make_error<StringError>( |
693 |
| - "port for -" + OutOfProcessExecutorConnect.ArgStr + " can not be empty", |
694 |
| - inconvertibleErrorCode()); |
695 |
| - |
696 |
| - std::string HostName = HostNameStr.str(); |
697 |
| - int Port = 0; |
698 |
| - if (PortStr.getAsInteger(10, Port)) |
699 |
| - return make_error<StringError>("port number " + PortStr + |
700 |
| - " is not a valid integer", |
701 |
| - inconvertibleErrorCode()); |
| 672 | +static Error createTCPSocketError(Twine Details) { |
| 673 | + return make_error<StringError>( |
| 674 | + formatv("Failed to connect TCP socket '{0}': {1}", |
| 675 | + OutOfProcessExecutorConnect, Details), |
| 676 | + inconvertibleErrorCode()); |
| 677 | +} |
702 | 678 |
|
| 679 | +static Expected<int> connectTCPSocket(std::string Host, std::string PortStr) { |
703 | 680 | addrinfo *AI;
|
704 | 681 | addrinfo Hints{};
|
705 | 682 | Hints.ai_family = AF_INET;
|
706 | 683 | Hints.ai_socktype = SOCK_STREAM;
|
707 | 684 | Hints.ai_flags = AI_NUMERICSERV;
|
708 |
| - if (int EC = |
709 |
| - getaddrinfo(HostName.c_str(), PortStr.str().c_str(), &Hints, &AI)) |
710 |
| - return make_error<StringError>(formatv("Failed to resolve {0}:{1} ({2})", |
711 |
| - HostName, Port, gai_strerror(EC)), |
712 |
| - inconvertibleErrorCode()); |
713 | 685 |
|
714 |
| - // getaddrinfo returns a list of address structures. Go through the list |
715 |
| - // to find one we can connect to. |
| 686 | + if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI)) |
| 687 | + return createTCPSocketError("Address resolution failed (" + |
| 688 | + StringRef(gai_strerror(EC)) + ")"); |
| 689 | + |
| 690 | + // Cycle through the returned addrinfo structures and connect to the first |
| 691 | + // reachable endpoint. |
716 | 692 | int SockFD;
|
717 |
| - int ConnectRC = -1; |
718 |
| - for (addrinfo *Server = AI; Server; Server = Server->ai_next) { |
719 |
| - // If socket fails, maybe it's because the address family is not supported. |
720 |
| - // Skip to the next addrinfo structure. |
| 693 | + addrinfo *Server; |
| 694 | + for (Server = AI; Server != nullptr; Server = Server->ai_next) { |
| 695 | + // socket might fail, e.g. if the address family is not supported. Skip to |
| 696 | + // the next addrinfo structure in such a case. |
721 | 697 | if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)
|
722 | 698 | continue;
|
723 | 699 |
|
724 |
| - ConnectRC = connect(SockFD, Server->ai_addr, Server->ai_addrlen); |
725 |
| - if (ConnectRC == 0) |
| 700 | + // If connect returns null, we exit the loop with a working socket. |
| 701 | + if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0) |
726 | 702 | break;
|
727 | 703 |
|
728 | 704 | close(SockFD);
|
729 | 705 | }
|
730 | 706 | freeaddrinfo(AI);
|
731 |
| - if (ConnectRC == -1) |
732 |
| - return make_error<StringError>("Failed to connect to " + HostName + ":" + |
733 |
| - Twine(Port), |
734 |
| - inconvertibleErrorCode()); |
| 707 | + |
| 708 | + // If we reached the end of the loop without connecting to a valid endpoint, |
| 709 | + // dump the last error that was logged in socket() or connect(). |
| 710 | + if (Server == nullptr) |
| 711 | + return createTCPSocketError(std::strerror(errno)); |
| 712 | + |
| 713 | + return SockFD; |
| 714 | +} |
| 715 | + |
| 716 | +Expected<std::unique_ptr<TargetProcessControl>> |
| 717 | +LLVMJITLinkRemoteTargetProcessControl::ConnectToExecutor() { |
| 718 | +#ifndef LLVM_ON_UNIX |
| 719 | + // FIXME: Add TCP support for Windows. |
| 720 | + return make_error<StringError>("-" + OutOfProcessExecutorConnect.ArgStr + |
| 721 | + " not supported on non-unix platforms", |
| 722 | + inconvertibleErrorCode()); |
| 723 | +#else |
| 724 | + |
| 725 | + shared::registerStringError<LLVMJITLinkChannel>(); |
| 726 | + |
| 727 | + StringRef Host, PortStr; |
| 728 | + std::tie(Host, PortStr) = StringRef(OutOfProcessExecutorConnect).split(':'); |
| 729 | + if (Host.empty()) |
| 730 | + return createTCPSocketError("Host name for -" + |
| 731 | + OutOfProcessExecutorConnect.ArgStr + |
| 732 | + " can not be empty"); |
| 733 | + if (PortStr.empty()) |
| 734 | + return createTCPSocketError("Port number in -" + |
| 735 | + OutOfProcessExecutorConnect.ArgStr + |
| 736 | + " can not be empty"); |
| 737 | + int Port = 0; |
| 738 | + if (PortStr.getAsInteger(10, Port)) |
| 739 | + return createTCPSocketError("Port number '" + PortStr + |
| 740 | + "' is not a valid integer"); |
| 741 | + |
| 742 | + Expected<int> SockFD = connectTCPSocket(Host.str(), PortStr.str()); |
| 743 | + if (!SockFD) |
| 744 | + return SockFD.takeError(); |
735 | 745 |
|
736 | 746 | auto SSP = std::make_shared<SymbolStringPool>();
|
737 |
| - auto Channel = std::make_unique<shared::FDRawByteChannel>(SockFD, SockFD); |
| 747 | + auto Channel = std::make_unique<shared::FDRawByteChannel>(*SockFD, *SockFD); |
738 | 748 | auto Endpoint = std::make_unique<LLVMJITLinkRPCEndpoint>(*Channel, true);
|
739 | 749 |
|
740 | 750 | auto ReportError = [](Error Err) {
|
|
0 commit comments