file_descriptor_shuffle.h revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef BASE_FILE_DESCRIPTOR_SHUFFLE_H_ 6#define BASE_FILE_DESCRIPTOR_SHUFFLE_H_ 7 8// This code exists to perform the shuffling of file descriptors which is 9// commonly needed when forking subprocesses. The naive approve is very simple, 10// just call dup2 to setup the desired descriptors, but wrong. It's tough to 11// handle the edge cases (like mapping 0 -> 1, 1 -> 0) correctly. 12// 13// In order to unittest this code, it's broken into the abstract action (an 14// injective multimap) and the concrete code for dealing with file descriptors. 15// Users should use the code like this: 16// base::InjectiveMultimap file_descriptor_map; 17// file_descriptor_map.push_back(base::InjectionArc(devnull, 0, true)); 18// file_descriptor_map.push_back(base::InjectionArc(devnull, 2, true)); 19// file_descriptor_map.push_back(base::InjectionArc(pipe[1], 1, true)); 20// base::ShuffleFileDescriptors(file_descriptor_map); 21// 22// and trust the the Right Thing will get done. 23 24#include <vector> 25 26namespace base { 27 28// A Delegate which performs the actions required to perform an injective 29// multimapping in place. 30class InjectionDelegate { 31 public: 32 // Duplicate |fd|, an element of the domain, and write a fresh element of the 33 // domain into |result|. Returns true iff successful. 34 virtual bool Duplicate(int* result, int fd) = 0; 35 // Destructively move |src| to |dest|, overwriting |dest|. Returns true iff 36 // successful. 37 virtual bool Move(int src, int dest) = 0; 38 // Delete an element of the domain. 39 virtual void Close(int fd) = 0; 40 41 protected: 42 virtual ~InjectionDelegate() {} 43}; 44 45// An implementation of the InjectionDelegate interface using the file 46// descriptor table of the current process as the domain. 47class FileDescriptorTableInjection : public InjectionDelegate { 48 bool Duplicate(int* result, int fd); 49 bool Move(int src, int dest); 50 void Close(int fd); 51}; 52 53// A single arc of the directed graph which describes an injective multimapping. 54struct InjectionArc { 55 InjectionArc(int in_source, int in_dest, bool in_close) 56 : source(in_source), 57 dest(in_dest), 58 close(in_close) { 59 } 60 61 int source; 62 int dest; 63 bool close; // if true, delete the source element after performing the 64 // mapping. 65}; 66 67typedef std::vector<InjectionArc> InjectiveMultimap; 68 69bool PerformInjectiveMultimap(const InjectiveMultimap& map, 70 InjectionDelegate* delegate); 71 72bool PerformInjectiveMultimapDestructive(InjectiveMultimap* map, 73 InjectionDelegate* delegate); 74 75// This function will not call malloc but will mutate |map| 76static inline bool ShuffleFileDescriptors(InjectiveMultimap* map) { 77 FileDescriptorTableInjection delegate; 78 return PerformInjectiveMultimapDestructive(map, &delegate); 79} 80 81} // namespace base 82 83#endif // BASE_FILE_DESCRIPTOR_SHUFFLE_H_ 84