diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index bfcd975..5c6129d 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -874,6 +874,27 @@ list_command (char *arg, int from_tty)
     {
       set_default_source_symtab_and_line ();
       cursal = get_current_source_symtab_and_line ();
+
+      /* If this is the first "list" since we've set the current
+	 source line, center the listing around that line.  */
+      if (get_first_line_listed () == 0)
+	{
+	  int first;
+
+	  first = max (cursal.line - get_lines_to_list () / 2, 1);
+
+	  /* A small special case --- if listing backwards, and we
+	     should list only one line, list the preceding line,
+	     instead of the exact line we've just shown after e.g.,
+	     stopping for a breakpoint.  */
+	  if (arg != NULL && arg[0] == '-'
+	      && get_lines_to_list () == 1 && first > 1)
+	    first -= 1;
+
+	  print_source_lines (cursal.symtab, first,
+			      first + get_lines_to_list (), 0);
+	  return;
+	}
     }
 
   /* "l" or "l +" lists next ten lines.  */
diff --git a/gdb/frame.h b/gdb/frame.h
index e451a93..6a75f0d 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -388,10 +388,9 @@ extern void find_frame_sal (struct frame_info *frame,
 			    struct symtab_and_line *sal);
 
 /* Set the current source and line to the location given by frame
-   FRAME, if possible.  When CENTER is true, adjust so the relevant
-   line is in the center of the next 'list'.  */
+   FRAME, if possible.  */
 
-void set_current_sal_from_frame (struct frame_info *, int);
+void set_current_sal_from_frame (struct frame_info *);
 
 /* Return the frame base (what ever that is) (DEPRECATED).
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index b7c0969..3d3ba55 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6091,7 +6091,7 @@ normal_stop (void)
      display the frame below, but the current SAL will be incorrect
      during a user hook-stop function.  */
   if (has_stack_frames () && !stop_stack_dummy)
-    set_current_sal_from_frame (get_current_frame (), 1);
+    set_current_sal_from_frame (get_current_frame ());
 
   /* Let the user/frontend see the threads as stopped.  */
   do_cleanups (old_chain);
diff --git a/gdb/source.c b/gdb/source.c
index c112765..c77a4f4 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -133,7 +133,9 @@ show_filename_display_string (struct ui_file *file, int from_tty,
 
 static int last_line_listed;
 
-/* First line number listed by last listing command.  */
+/* First line number listed by last listing command.  If 0, then no
+   source lines have yet been listed since the last time the current
+   source line was changed.  */
 
 static int first_line_listed;
 
@@ -153,6 +155,16 @@ get_first_line_listed (void)
   return first_line_listed;
 }
 
+/* Clear line listed range.  This makes the next "list" center the
+   printed source lines around the current source line.  */
+
+static void
+clear_lines_listed_range (void)
+{
+  first_line_listed = 0;
+  last_line_listed = 0;
+}
+
 /* Return the default number of lines to print with commands like the
    cli "list".  The caller of print_source_lines must use this to
    calculate the end line and use it in the call to print_source_lines
@@ -220,6 +232,9 @@ set_current_source_symtab_and_line (const struct symtab_and_line *sal)
   current_source_symtab = sal->symtab;
   current_source_line = sal->line;
 
+  /* Force the next "list" to center around the current line.  */
+  clear_lines_listed_range ();
+
   return cursal;
 }
 
@@ -1294,9 +1309,8 @@ identify_source_line (struct symtab *s, int line, int mid_statement,
 		   mid_statement, get_objfile_arch (s->objfile), pc);
 
   current_source_line = line;
-  first_line_listed = line;
-  last_line_listed = line;
   current_source_symtab = s;
+  clear_lines_listed_range ();
   return 1;
 }
 
@@ -1488,7 +1502,11 @@ line_info (char *arg, int from_tty)
     {
       sal.symtab = current_source_symtab;
       sal.pspace = current_program_space;
-      sal.line = last_line_listed;
+      if (last_line_listed != 0)
+	sal.line = last_line_listed;
+      else
+	sal.line = current_source_line;
+
       sals.nelts = 1;
       sals.sals = (struct symtab_and_line *)
 	xmalloc (sizeof (struct symtab_and_line));
diff --git a/gdb/source.h b/gdb/source.h
index 61826ea..ad74df9 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -62,9 +62,10 @@ extern const char *symtab_to_filename_for_display (struct symtab *symtab);
    lines.  */
 extern void find_source_lines (struct symtab *s, int desc);
 
-/* Return the first line listed by print_source_lines.
-   Used by command interpreters to request listing from
-   a previous point.  */
+/* Return the first line listed by print_source_lines.  Used by
+   command interpreters to request listing from a previous point.  If
+   0, then no source lines have yet been listed since the last time
+   the current source line was changed.  */
 extern int get_first_line_listed (void);
 
 /* Return the default number of lines to print with commands like the
diff --git a/gdb/stack.c b/gdb/stack.c
index da7d977..0c6923d 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -166,12 +166,10 @@ print_stack_frame (struct frame_info *frame, int print_level,
 
   TRY_CATCH (e, RETURN_MASK_ERROR)
     {
-      int center = (print_what == SRC_LINE || print_what == SRC_AND_LOC);
-
       print_frame_info (frame, print_level, print_what, 1 /* print_args */,
 			set_current_sal);
       if (set_current_sal)
-	set_current_sal_from_frame (frame, center);
+	set_current_sal_from_frame (frame);
     }
 }
 
@@ -716,17 +714,13 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
    line is in the center of the next 'list'.  */
 
 void
-set_current_sal_from_frame (struct frame_info *frame, int center)
+set_current_sal_from_frame (struct frame_info *frame)
 {
   struct symtab_and_line sal;
 
   find_frame_sal (frame, &sal);
-  if (sal.symtab)
-    {
-      if (center)
-        sal.line = max (sal.line - get_lines_to_list () / 2, 1);
-      set_current_source_symtab_and_line (&sal);
-    }
+  if (sal.symtab != NULL)
+    set_current_source_symtab_and_line (&sal);
 }
 
 /* If ON, GDB will display disassembly of the next source line when
diff --git a/gdb/testsuite/gdb.base/list.exp b/gdb/testsuite/gdb.base/list.exp
index 12b2c94..67eef12 100644
--- a/gdb/testsuite/gdb.base/list.exp
+++ b/gdb/testsuite/gdb.base/list.exp
@@ -529,4 +529,98 @@ if [ set_listsize 10 ] then {
     test_only_end
 }
 
+# Follows tests that require execution.
+
+# Build source listing pattern based on a line range spec string.  The
+# range can be specificed as "START-END" indicating all lines in range
+# (inclusive); or just "LINE", indicating just that line.
+
+proc build_pattern { range_spec } {
+    global line_re
+
+    set range_list [split $range_spec -]
+    set range_list_len [llength $range_list]
+
+    set range_start [lindex $range_list 0]
+    if { $range_list_len > 2 || $range_list_len < 1} {
+	error "invalid range spec string: $range_spec"
+    } elseif { $range_list_len == 2 } {
+	set range_end [lindex $range_list 1]
+    } else {
+	set range_end $range_start
+    }
+
+    for {set i $range_start} {$i <= $range_end} {incr i} {
+	append pattern "\r\n$i\[ \t\]\[^\r\n\]*"
+    }
+
+    verbose -log "pattern $pattern"
+    return $pattern
+}
+
+# Test "list" command invocations right after stopping for an event.
+# COMMAND is the actual list command, including arguments.  LISTSIZE1
+# and LISTSIZE2 are the listsizes set just before and after running
+# the program to the stop point.  COMMAND is issued twice.  The first
+# time, the lines specificed by LINERANGE1 are expected; the second
+# time, the lines specified by LINERANGE2 are expected.
+
+proc test_list {command listsize1 listsize2 linerange1 linerange2} {
+    with_test_prefix "$command after stop: $listsize1, $listsize2" {
+	global binfile
+
+	clean_restart $binfile
+	if ![runto_main] then {
+	    fail "Can't run to main"
+	    return
+	}
+
+	# Test changing the listsize both before nexting, and after
+	# stopping, but before listing.  Only the second listsize
+	# change should affect which lines are listed.
+	gdb_test_no_output "set listsize $listsize1"
+	gdb_test "next" "foo \\(.*"
+	gdb_test_no_output "set listsize $listsize2"
+
+	set pattern1 [build_pattern $linerange1]
+	set pattern2 [build_pattern $linerange2]
+	gdb_test "$command" "${pattern1}" "$command #1"
+	gdb_test "$command" "${pattern2}" "$command #2"
+    }
+}
+
+
+# The first "list" should center the listing around line 8, the stop
+# line.
+test_list "list" 1 10 "3-12" "13-22"
+
+# Likewise.
+test_list "list" 10 10 "3-12" "13-22"
+
+# Likewise, but show only one line.  IOW, the first list should show
+# line 8.  Note how the listsize is 10 at the time of the stop, but
+# before any listing had been requested.  That should not affect the
+# line range that is first listed.
+test_list "list" 10 1 "8" "9"
+
+# Likewise, but show two lines.
+test_list "list" 10 2 "7-8" "9-10"
+
+# Three lines.
+test_list "list" 10 3 "7-9" "10-12"
+
+# Now test backwards.  Just like "list", the first "list -" should
+# center the listing around the stop line.
+test_list "list -" 10 10 "3-12" "2"
+
+# Likewise, but test showing 3 lines at a time.
+test_list "list -" 10 3 "7-9" "4-6"
+
+# 2 lines at a time.
+test_list "list -" 10 2 "7-8" "5-6"
+
+# Test listing one line one.  This case is a little special, and
+# starts showing the previous line immediately.
+test_list "list -" 10 1 "7" "6"
+
 remote_exec build "rm -f list0.h"
diff --git a/gdb/testsuite/gdb.mi/mi-cli.exp b/gdb/testsuite/gdb.mi/mi-cli.exp
index 5657be6..566d64d 100644
--- a/gdb/testsuite/gdb.mi/mi-cli.exp
+++ b/gdb/testsuite/gdb.mi/mi-cli.exp
@@ -65,6 +65,7 @@ set line_main_head    [gdb_get_line_number "main ("]
 set line_main_body    [expr $line_main_head + 2]
 set line_main_hello   [gdb_get_line_number "Hello, World!"]
 set line_main_return  [expr $line_main_hello + 2]
+set line_main_callme_2 [expr $line_main_return + 1]
 set line_callee4_head [gdb_get_line_number "callee4 ("]
 set line_callee4_body [expr $line_callee4_head + 2]
 set line_callee4_next [expr $line_callee4_body + 1]
@@ -184,6 +185,25 @@ mi_gdb_test "-interpreter-exec console \"list\"" \
   "\~\"$line_main_return\[\\\\t ]*callme \\(1\\);\\\\n\".*\\^done" \
   "-interpreter-exec console \"list\" at basics.c:\$line_main_return"
 
+mi_gdb_test "600-break-insert -t basics.c:$line_main_callme_2" \
+	{600\^done,bkpt=.number="4",type="breakpoint".*\}} \
+	"-break-insert -t basics.c:\$line_main_callme_2"
+
+mi_execute_to "exec-continue" "breakpoint-hit" "main" "" ".*basics.c" \
+    $line_main_callme_2 { "" "disp=\"del\"" } \
+    "-exec-continue to line \$line_main_callme_2"
+
+# Restore the listsize back to the default.
+mi_gdb_test "-interpreter-exec console \"set listsize 10\"" \
+  ".*=cmd-param-changed,param=\"listsize\",value=\"10\".*\\^done" \
+  "-interpreter-exec console \"set listsize 10\""
+
+# "list" should show 10 lines centered on where the program stopped.
+set first_list_line [expr $line_main_callme_2 - 5]
+mi_gdb_test "-interpreter-exec console \"list\"" \
+    ".*\~\"$first_list_line.*\\^done" \
+    "-interpreter-exec console \"list\" at basics.c:\$line_main_return"
+
 mi_gdb_test "-interpreter-exec console \"help set args\"" \
   {\~"Set argument list to give program being debugged when it is started\.\\nFollow this command with any number of args, to be passed to the program\.".*\^done} \
   "-interpreter-exec console \"help set args\""
diff --git a/gdb/testsuite/gdb.python/python.exp b/gdb/testsuite/gdb.python/python.exp
index a470427..2b7d78e 100644
--- a/gdb/testsuite/gdb.python/python.exp
+++ b/gdb/testsuite/gdb.python/python.exp
@@ -168,7 +168,8 @@ if ![runto_main] then {
     return 0
 }
 
-runto [gdb_get_line_number "Break to end."]
+set lineno [gdb_get_line_number "Break to end."]
+runto $lineno
 
 # Test gdb.decode_line.
 gdb_test "python gdb.decode_line(\"main.c:43\")" \
@@ -179,7 +180,7 @@ gdb_test "python print (len(symtab))" "2" "Test decode_line current location"
 gdb_test "python print (symtab\[0\])" "None" "Test decode_line expression parse"
 gdb_test "python print (len(symtab\[1\]))" "1" "Test decode_line current location"
 gdb_test "python print (symtab\[1\]\[0\].symtab)" ".*gdb.python/python.c.*" "Test decode_line current locationn filename"
-gdb_test "python print (symtab\[1\]\[0\].line)" "22" "Test decode_line current location line number"
+gdb_test "python print (symtab\[1\]\[0\].line)" "$lineno" "Test decode_line current location line number"
 
 gdb_py_test_silent_cmd "python symtab = gdb.decode_line(\"python.c:26 if foo\")" "test decode_line python.c:26" 1
 gdb_test "python print (len(symtab))" "2" "Test decode_line python.c:26 length"
