aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Asim Shankar <ashankar@google.com>2016-11-08 15:33:46 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-11-08 16:34:44 -0800
commit7f498fa85380235f4c96bbb6bc99219f13caa2be (patch)
tree7289c1c32f203ba4a11870e5f92fbcdcb13c5526
parent6e53bedeb8f4e05a47307ce92ba584144243f52e (diff)
Handle partitioning of incomplete graphs gracefully.
The added test would lead to a SIGSEGV without the accompanying changes in graph_partition.cc. In practice, this code path can be triggered by invoking: Session::Extend(graph_def); followed by: Session::Run() when graph_def incompletely specifies a graph (such as the one in the test, where not all inputs of the target node have been specified). Change: 138573807
-rw-r--r--tensorflow/core/graph/graph_partition.cc8
-rw-r--r--tensorflow/core/graph/graph_partition_test.cc27
2 files changed, 35 insertions, 0 deletions
diff --git a/tensorflow/core/graph/graph_partition.cc b/tensorflow/core/graph/graph_partition.cc
index 488fe47f38..8e9eceb699 100644
--- a/tensorflow/core/graph/graph_partition.cc
+++ b/tensorflow/core/graph/graph_partition.cc
@@ -857,6 +857,7 @@ Status Partition(const PartitionOptions& opts, Graph* g,
ref_control_inputs.clear();
const Edge* control_flow_edge = nullptr;
int32 num_control_flow_edges = 0;
+ int32 num_input_edges = 0;
for (const Edge* edge : dst->in_edges()) {
if (edge->IsControlEdge()) {
if (IsMerge(edge->src()) && IsControlLoop(edge->src())) {
@@ -871,9 +872,16 @@ Status Partition(const PartitionOptions& opts, Graph* g,
} else {
DCHECK(inputs[edge->dst_input()] == nullptr);
inputs[edge->dst_input()] = edge;
+ ++num_input_edges;
}
}
+ if (num_input_edges != dst->num_inputs()) {
+ return errors::InvalidArgument("Incomplete graph, missing ",
+ (dst->num_inputs() - num_input_edges),
+ " inputs for ", dst->name());
+ }
+
// Process in order so that all data edges are added as inputs to
// dst in Edge::dst_input() order.
for (const Edge* edge : inputs) {
diff --git a/tensorflow/core/graph/graph_partition_test.cc b/tensorflow/core/graph/graph_partition_test.cc
index 34342ff4f3..24bc8dd575 100644
--- a/tensorflow/core/graph/graph_partition_test.cc
+++ b/tensorflow/core/graph/graph_partition_test.cc
@@ -372,5 +372,32 @@ TEST_F(GraphPartitionTest, CrossDeviceLoop1) {
}
}
+TEST_F(GraphPartitionTest, PartitionIncompleteGraph) {
+ NodeDef ndef;
+ Graph g(OpRegistry::Global());
+ // Invalid graph since the Combine node requires an input.
+ bool parsed = protobuf::TextFormat::ParseFromString(
+ R"EOF(
+ name: "N"
+ op: "Combine"
+ )EOF",
+ &ndef);
+ ASSERT_TRUE(parsed);
+ Status status;
+ g.AddNode(ndef, &status);
+ TF_ASSERT_OK(status);
+
+ PartitionOptions popts;
+ popts.node_to_loc = SplitByDevice;
+ popts.new_name = [&g](const string& prefix) { return g.NewName(prefix); };
+ popts.get_incarnation = [](const string&) { return 1; };
+
+ std::unordered_map<string, GraphDef> partitions;
+ status = Partition(popts, &g, &partitions);
+ // Partitioning should fail, but not crash like it did before the
+ // changes that accompanied the addition of this test.
+ EXPECT_EQ(error::INVALID_ARGUMENT, status.code()) << status;
+}
+
} // namespace
} // namespace tensorflow