2525#include " lldb/Utility/UriParser.h"
2626#include " lldb/lldb-forward.h"
2727#include " llvm/ADT/ArrayRef.h"
28+ #include " llvm/ADT/DenseMap.h"
2829#include " llvm/ADT/ScopeExit.h"
2930#include " llvm/ADT/SmallVector.h"
3031#include " llvm/ADT/StringExtras.h"
4445#include " llvm/Support/WithColor.h"
4546#include " llvm/Support/raw_ostream.h"
4647#include < condition_variable>
48+ #include < cstddef>
4749#include < cstdio>
4850#include < cstdlib>
51+ #include < exception>
4952#include < fcntl.h>
5053#include < map>
5154#include < memory>
@@ -146,14 +149,19 @@ static void PrintVersion() {
146149}
147150
148151#if not defined(_WIN32)
149- static llvm::Error RedirectToFile (int fd, llvm::StringRef file, bool read,
150- bool write) {
151- if (!read && !write)
152+ struct FDGroup {
153+ std::vector<int > fds;
154+ bool read = false ;
155+ bool write = false ;
156+ };
157+
158+ static llvm::Error RedirectToFile (const FDGroup &fdg, llvm::StringRef file) {
159+ if (!fdg.read && !fdg.write )
152160 return llvm::Error::success ();
153161 int flags = 0 ;
154- if (read && write)
162+ if (fdg. read && fdg. write )
155163 flags = O_NOCTTY | O_CREAT | O_RDWR;
156- else if (read)
164+ else if (fdg. read )
157165 flags = O_NOCTTY | O_RDONLY;
158166 else
159167 flags = O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC;
@@ -162,36 +170,47 @@ static llvm::Error RedirectToFile(int fd, llvm::StringRef file, bool read,
162170 if (target_fd == -1 )
163171 return llvm::errorCodeToError (
164172 std::error_code (errno, std::generic_category ()));
165- if (target_fd == fd)
166- return llvm::Error::success ();
167- if (dup2 (target_fd, fd) == -1 )
168- return llvm::errorCodeToError (
169- std::error_code (errno, std::generic_category ()));
170- close (target_fd);
173+ for (int fd : fdg.fds ) {
174+ if (target_fd == fd)
175+ continue ;
176+ if (::dup2 (target_fd, fd) == -1 )
177+ return llvm::errorCodeToError (
178+ std::error_code (errno, std::generic_category ()));
179+ }
180+ ::close (target_fd);
171181 return llvm::Error::success ();
172182}
173183
174184static llvm::Error
175185SetupIORedirection (const llvm::SmallVectorImpl<llvm::StringRef> &files) {
176- for (std::size_t i = 0 ; i < files.size (); i++) {
186+ llvm::SmallDenseMap<llvm::StringRef, FDGroup> groups;
187+ for (size_t i = 0 ; i < files.size (); i++) {
177188 if (files[i].empty ())
178189 continue ;
190+ auto group = groups.find (files[i]);
191+ if (group == groups.end ())
192+ group = groups.insert ({files[i], {{static_cast <int >(i)}}}).first ;
193+ else
194+ group->second .fds .push_back (i);
179195 switch (i) {
180196 case 0 :
181- if (llvm::Error err = RedirectToFile (i, files[i], true , false ))
182- return err;
197+ group->second .read = true ;
183198 break ;
184199 case 1 :
185200 case 2 :
186- if (llvm::Error err = RedirectToFile (i, files[i], false , true ))
187- return err;
201+ group->second .write = true ;
188202 break ;
189203 default :
190- if (llvm::Error err = RedirectToFile (i, files[i], true , true ))
191- return err ;
204+ group-> second . read = true ;
205+ group-> second . write = true ;
192206 break ;
193207 }
194208 }
209+ for (const auto &[file, group] : groups) {
210+ if (llvm::Error err = RedirectToFile (group, file))
211+ return llvm::createStringError (
212+ llvm::formatv (" {0}: {1}" , file, llvm::toString (std::move (err))));
213+ }
195214 return llvm::Error::success ();
196215}
197216#endif
0 commit comments