View | Details | Raw Unified | Return to bug 28942
Collapse All | Expand All

(-)a/gdb/breakpoint.c (+2 lines)
Lines 5234-5239 bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread) Link Here
5234
      return;
5236
      return;
5235
    }
5237
    }
5236
5238
5239
  scoped_restore restore_non_stop = make_scoped_restore (&non_stop, 1);
5240
5237
  /* Evaluate extension language breakpoints that have a "stop" method
5241
  /* Evaluate extension language breakpoints that have a "stop" method
5238
     implemented.  */
5242
     implemented.  */
5239
  bs->stop = breakpoint_ext_lang_cond_says_stop (b);
5243
  bs->stop = breakpoint_ext_lang_cond_says_stop (b);
(-)a/gdb/testsuite/gdb.threads/all-stop-infcall.c (+230 lines)
Line 0 Link Here
1
/* This testcase is part of GDB, the GNU debugger.
2
3
   Copyright 2022 Free Software Foundation, Inc.
4
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License as published by
7
   the Free Software Foundation; either version 3 of the License, or
8
   (at your option) any later version.
9
10
   This program is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU General Public License for more details.
14
15
   You should have received a copy of the GNU General Public License
16
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18
#include <stdio.h>
19
#include <pthread.h>
20
#include <unistd.h>
21
#include <stdlib.h>
22
#include <errno.h>
23
24
/* Holds a thread id, and the pipe file descriptors used to talk between
25
   the child and parent thread.  */
26
27
struct thread_info
28
{
29
  /* The thread handle.  */
30
  pthread_t id;
31
32
  /* Pipe where the write end is for the parent, and the read end is for
33
     the thread.   */
34
  int to_thread[2];
35
36
37
  /* Pipe where the write end is for the thread, and the read end is for
38
     the parent.  */
39
  int to_parent[2];
40
};
41
42
/* A global value. We use this for the breakpoint condition, but access it
43
   through get_global_value.  */
44
45
int global_value = 0;
46
47
/* An function to read global_value, calling this from the breakpoint
48
   condition will require an inferior function call.  */
49
50
int
51
get_global_value ()
52
{
53
  char buf[1024];
54
55
  snprintf (buf, sizeof (buf), "get_global_value (%d)", global_value);
56
  puts (buf);
57
  return global_value;
58
}
59
60
/* Another function to call from a breakpoint condition, this one will
61
   trigger a segfault.  */
62
63
void
64
function_that_segfaults (void)
65
{
66
  int *p = 0;
67
  *p = 1;	/* Segfault happens here.   */
68
}
69
70
/* Wait for a single byte on the read end of PIPE (that is PIPE[0]).  */
71
72
void
73
wait_for_byte (int pipe[2])
74
{
75
  ssize_t res;
76
  char buf;
77
78
  do
79
    {
80
      res = read (pipe[0], &buf, sizeof (buf));
81
    }
82
  while (res == -1 && errno == EINTR);
83
  if (res != sizeof (buf))
84
    abort ();
85
}
86
87
/* Send a single byte to the write end of PIPE (that is PIPE[1]).  */
88
89
void
90
send_byte (int pipe[2])
91
{
92
  ssize_t res;
93
  char buf = 'x';
94
95
  do
96
    {
97
      res = write (pipe[1], &buf, sizeof (buf));
98
    }
99
  while (res == -1 && errno == EINTR);
100
  if (res != sizeof (buf))
101
    {
102
      perror ("write");
103
      abort ();
104
    }
105
}
106
107
/* Create a new thread, and the pipes to talk between the new child thread
108
   and this, the parent thread.  Return 0 on success, -1 on error.  */
109
110
int
111
create_thread (void *(*func) (void *),
112
	       struct thread_info *info)
113
{
114
  if (pipe (info->to_thread) < 0)
115
    return -1;
116
  if (pipe (info->to_parent) < 0)
117
    return -1;
118
119
  if (pthread_create (&info->id, NULL, func, info) != 0)
120
    return -1;
121
122
  return 0;
123
}
124
125
/* Join with the child thread identified by INFO.  Return 0 on success, -1
126
   on error.  */
127
128
int
129
join_thread (struct thread_info *info)
130
{
131
  if (pthread_join (info->id, NULL) != 0)
132
    return -1;
133
134
  return 0;
135
}
136
137
/* An empty function, place breakpoints on this.  */
138
139
void
140
breakpt ()
141
{
142
  /* Nothing.  */
143
}
144
145
/* The thread worker function.  */
146
147
void *
148
thread_func (void *arg)
149
{
150
  struct thread_info *info = (struct thread_info *) arg;
151
152
  /* (1) Send to the parent thread.  */
153
  puts ("(1) child thread: send to parent");
154
  send_byte (info->to_parent);
155
156
  /* (2) Wait for the parent thread.  */
157
  puts ("(2) child thread: wait for byte.");
158
  wait_for_byte (info->to_thread);
159
160
  /* (3) Send to the parent thread.  */
161
  puts ("(3) child thread: send to parent");
162
  send_byte (info->to_parent);
163
164
  /* (4) Wait for the parent thread.  */
165
  puts ("(4) child thread: wait for byte.");
166
  wait_for_byte (info->to_thread);
167
168
  /* (5) Send to the parent thread.  */
169
  puts ("(5) child thread: send to parent");
170
  send_byte (info->to_parent);
171
172
  return NULL;
173
}
174
175
/* The main program entry point.  */
176
177
int
178
main ()
179
{
180
  struct thread_info info;
181
182
  puts ("(0) parent thread: creating child thread.");
183
  if (create_thread (thread_func, &info) < 0)
184
    abort ();
185
186
  /* (1) Wait for child thread.  */
187
  puts ("(1) parent thread: wait for child.");
188
  wait_for_byte (info.to_parent);
189
190
 /* If we stop at a breakpoint now then the child thread will be running
191
     while the breakpoint condition is evaluated.  */
192
  puts("    parent thread: calling breakpt.");
193
  breakpt ();
194
195
  /* Now we want to make sure that the child thread is still running
196
     correctly, and GDB hasn't accidentally left the thread stopped.  */
197
198
  /* (2) Send to child thread.  */
199
  puts("(2) parent thread: sending byte to child thread.");
200
  send_byte (info.to_thread);
201
202
  /* (3) Wait for child thread.  */
203
  puts ("(3) parent thread: wait for child.");
204
  wait_for_byte (info.to_parent);
205
206
  /* We now know that the child is alive and running.  Call breakpoint
207
     function again, this time the global value is such that the breakpoint
208
     should trigger.  */
209
210
  global_value = 1;
211
  puts("    parent thread: calling breakpt.");
212
  breakpt ();
213
214
  /* Once again, we want to ensure that the child is alive and kicking .  */
215
216
  /* (4) Send to child thread.  */
217
  puts("(4) parent thread: sending byte to child thread.");
218
  send_byte (info.to_thread);
219
220
  /* (5) Wait for child thread.  */
221
  puts ("(5) parent thread: wait for child.");
222
  wait_for_byte (info.to_parent);
223
224
  puts ("Joining with child thread.");
225
226
  if (join_thread (&info) < 0)
227
    abort ();
228
229
  return 0;
230
}
(-)a/gdb/testsuite/gdb.threads/all-stop-infcall.exp (+109 lines)
Line 0 Link Here
1
# Copyright 2022 Free Software Foundation, Inc.
2
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 3 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16
standard_testfile
17
18
if {[prepare_for_testing "failed to prepare" \
19
	 $testfile $srcfile {debug pthreads}] == -1} {
20
    return -1
21
}
22
23
if ![runto_main] then {
24
    return 0
25
}
26
27
# Check that we have two threads, and that neither thread is running.
28
proc check_threads { } {
29
30
    array set threads {}
31
32
    gdb_test_multiple "info threads" "" {
33
	-re "^info threads\r\n" {
34
	    verbose -log "APB: Saw command"
35
	    exp_continue
36
	}
37
38
	-re "^\\s+Id\\s+Target Id\\s+Frame\\s+\r\n" {
39
	    verbose -log "APB: Saw header line"
40
	    exp_continue
41
	}
42
43
	-re "^((\\*| )\\s+($::decimal)\\s+\[^\r\n\]+)\r\n" {
44
	    set status $expect_out(1,string)
45
	    set num $expect_out(3,string)
46
	    set threads($num) $status
47
	    verbose -log "APB: Saw thread $num line: $status"
48
	    exp_continue
49
	}
50
51
	-re "$::gdb_prompt $" {
52
	    pass $gdb_test_name
53
	}
54
    }
55
56
    # Check that we saw both threads, and that neither thread is in
57
    # the running state.
58
    foreach num { 1 2 } {
59
	gdb_assert [info exists threads($num)] "check thread $num was found"
60
61
	gdb_assert {[string first "(running)" $threads($num)] == -1} \
62
	    "thread $num is not running"
63
    }
64
}
65
66
# In this first test we call an inferior function from a breakpoint
67
# condition.  The first time the condition will evaluate to false, and
68
# the second time the condition evaluates to true.  The second
69
# breakpoint location will only be hit if the other thread keeps
70
# running after the breakpoint condition is evaluated.
71
72
with_test_prefix "basic case" {
73
    gdb_breakpoint "breakpt if get_global_value () > 0"
74
    gdb_continue_to_breakpoint "breakpt"
75
    gdb_test "p global_value" " = 1"
76
    check_threads
77
}
78
79
# In the next test we call an inferior function that segfaults from a
80
# breakpoint condition.
81
82
with_test_prefix "with_segfault" {
83
84
    clean_restart ${binfile}
85
86
    if ![runto_main] then {
87
	return 0
88
    }
89
90
    gdb_breakpoint "breakpt if function_that_segfaults ()"
91
92
    set lineno [gdb_get_line_number "Segfault happens here"]
93
    gdb_test "continue" \
94
	[multi_line \
95
	     "Error in testing breakpoint condition:" \
96
	     "The program being debugged was signaled while in a function called from GDB." \
97
	     "GDB remains in the frame where the signal was received." \
98
	     "To change this behavior use \"set unwindonsignal on\"\\." \
99
	     "Evaluation of the expression containing the function" \
100
	     "\\(function_that_segfaults\\) will be abandoned." \
101
	     "When the function is done executing, GDB will silently stop." \
102
	     "" \
103
	     "Thread 1 \"all-stop-infcal\" received signal SIGSEGV, Segmentation fault\\." \
104
	     "" \
105
	     "Thread 1 \"all-stop-infcal\" hit Breakpoint $decimal, $hex in function_that_segfaults \\(\\) at \[^\r\n\]+/all-stop-infcall.c:${lineno}" \
106
	     "${lineno}\\s+\\*p = 1;\[^\r\n\]+"]
107
108
    check_threads
109
}

Return to bug 28942