Procházet zdrojové kódy

Fixing issue of docker top command failure when dealing with -m option
Changed per requested review to refactor to make it more logic clear.

Current output for "docker top <contianer-id> m" option,eg:
root@b2c7ec58399d:/go/src/github.com/docker/docker# docker top 755d5871ec45 am
PID TTY STAT TIME COMMAND
148 pts/0 - 0:00 bash
- - Ss+ 0:00 -

fixing issue:#30580

Signed-off-by: catinthesky <yaozaiyong@hotmail.com>

catinthesky před 8 roky
rodič
revize
a7497c39cd
2 změnil soubory, kde provedl 41 přidání a 9 odebrání
  1. 38 9
      daemon/top_unix.go
  2. 3 0
      daemon/top_unix_test.go

+ 38 - 9
daemon/top_unix.go

@@ -41,6 +41,23 @@ func fieldsASCII(s string) []string {
 	return strings.FieldsFunc(s, fn)
 }
 
+func appendProcess2ProcList(procList *container.ContainerTopOKBody, fields []string) {
+	// Make sure number of fields equals number of header titles
+	// merging "overhanging" fields
+	process := fields[:len(procList.Titles)-1]
+	process = append(process, strings.Join(fields[len(procList.Titles)-1:], " "))
+	procList.Processes = append(procList.Processes, process)
+}
+
+func hasPid(pids []int, pid int) bool {
+	for _, i := range pids {
+		if i == pid {
+			return true
+		}
+	}
+	return false
+}
+
 func parsePSOutput(output []byte, pids []int) (*container.ContainerTopOKBody, error) {
 	procList := &container.ContainerTopOKBody{}
 
@@ -58,25 +75,37 @@ func parsePSOutput(output []byte, pids []int) (*container.ContainerTopOKBody, er
 	}
 
 	// loop through the output and extract the PID from each line
+	// fixing #30580, be able to display thread line also when "m" option used
+	// in "docker top" client command
+	preContainedPidFlag := false
 	for _, line := range lines[1:] {
 		if len(line) == 0 {
 			continue
 		}
 		fields := fieldsASCII(line)
-		p, err := strconv.Atoi(fields[pidIndex])
+
+		var (
+			p   int
+			err error
+		)
+
+		if fields[pidIndex] == "-" {
+			if preContainedPidFlag {
+				appendProcess2ProcList(procList, fields)
+			}
+			continue
+		}
+		p, err = strconv.Atoi(fields[pidIndex])
 		if err != nil {
 			return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
 		}
 
-		for _, pid := range pids {
-			if pid == p {
-				// Make sure number of fields equals number of header titles
-				// merging "overhanging" fields
-				process := fields[:len(procList.Titles)-1]
-				process = append(process, strings.Join(fields[len(procList.Titles)-1:], " "))
-				procList.Processes = append(procList.Processes, process)
-			}
+		if hasPid(pids, p) {
+			preContainedPidFlag = true
+			appendProcess2ProcList(procList, fields)
+			continue
 		}
+		preContainedPidFlag = false
 	}
 	return procList, nil
 }

+ 3 - 0
daemon/top_unix_test.go

@@ -42,17 +42,20 @@ func TestContainerTopParsePSOutput(t *testing.T) {
 		{[]byte(`  PID COMMAND
    42 foo
    43 bar
+		- -
   100 baz
 `), []int{42, 43}, false},
 		{[]byte(`  UID COMMAND
    42 foo
    43 bar
+		- -
   100 baz
 `), []int{42, 43}, true},
 		// unicode space (U+2003, 0xe2 0x80 0x83)
 		{[]byte(` PID COMMAND
    42 foo
    43 bar
+		- -
   100 baz
 `), []int{42, 43}, true},
 		// the first space is U+2003, the second one is ascii.