@@ -40,6 +40,7 @@ struct child {
4040 int pid ;
4141 int tid ;
4242 pthread_t thread ;
43+ char stack [65536 ];
4344};
4445
4546static void release_child (struct child * child )
@@ -69,41 +70,56 @@ static void kick_child(struct child *child)
6970 fflush (NULL );
7071}
7172
72- static int spawn_child ( struct child * child )
73+ static int child_func ( void * arg )
7374{
75+ struct child * child = arg ;
7476 int err , c ;
7577
78+ close (child -> go [1 ]);
79+
80+ /* wait for parent's kick */
81+ err = read (child -> go [0 ], & c , 1 );
82+ if (err != 1 )
83+ exit (err );
84+
85+ uprobe_multi_func_1 ();
86+ uprobe_multi_func_2 ();
87+ uprobe_multi_func_3 ();
88+ usdt_trigger ();
89+
90+ exit (errno );
91+ }
92+
93+ static int spawn_child_flag (struct child * child , bool clone_vm )
94+ {
7695 /* pipe to notify child to execute the trigger functions */
7796 if (pipe (child -> go ))
7897 return -1 ;
7998
80- child -> pid = child -> tid = fork ();
99+ if (clone_vm ) {
100+ child -> pid = child -> tid = clone (child_func , child -> stack + sizeof (child -> stack )/2 ,
101+ CLONE_VM |SIGCHLD , child );
102+ } else {
103+ child -> pid = child -> tid = fork ();
104+ }
81105 if (child -> pid < 0 ) {
82106 release_child (child );
83107 errno = EINVAL ;
84108 return -1 ;
85109 }
86110
87- /* child */
88- if (child -> pid == 0 ) {
89- close (child -> go [1 ]);
90-
91- /* wait for parent's kick */
92- err = read (child -> go [0 ], & c , 1 );
93- if (err != 1 )
94- exit (err );
95-
96- uprobe_multi_func_1 ();
97- uprobe_multi_func_2 ();
98- uprobe_multi_func_3 ();
99- usdt_trigger ();
100-
101- exit (errno );
102- }
111+ /* fork-ed child */
112+ if (!clone_vm && child -> pid == 0 )
113+ child_func (child );
103114
104115 return 0 ;
105116}
106117
118+ static int spawn_child (struct child * child )
119+ {
120+ return spawn_child_flag (child , false);
121+ }
122+
107123static void * child_thread (void * ctx )
108124{
109125 struct child * child = ctx ;
@@ -948,7 +964,7 @@ static struct bpf_program *uprobe_multi_program(struct uprobe_multi_pid_filter *
948964
949965#define TASKS 3
950966
951- static void run_pid_filter (struct uprobe_multi_pid_filter * skel , bool retprobe )
967+ static void run_pid_filter (struct uprobe_multi_pid_filter * skel , bool clone_vm , bool retprobe )
952968{
953969 LIBBPF_OPTS (bpf_uprobe_multi_opts , opts , .retprobe = retprobe );
954970 struct bpf_link * link [TASKS ] = {};
@@ -958,7 +974,7 @@ static void run_pid_filter(struct uprobe_multi_pid_filter *skel, bool retprobe)
958974 memset (skel -> bss -> test , 0 , sizeof (skel -> bss -> test ));
959975
960976 for (i = 0 ; i < TASKS ; i ++ ) {
961- if (!ASSERT_OK (spawn_child (& child [i ]), "spawn_child" ))
977+ if (!ASSERT_OK (spawn_child_flag (& child [i ], clone_vm ), "spawn_child" ))
962978 goto cleanup ;
963979 skel -> bss -> pids [i ] = child [i ].pid ;
964980 }
@@ -986,16 +1002,16 @@ static void run_pid_filter(struct uprobe_multi_pid_filter *skel, bool retprobe)
9861002 release_child (& child [i ]);
9871003}
9881004
989- static void test_pid_filter_process (void )
1005+ static void test_pid_filter_process (bool clone_vm )
9901006{
9911007 struct uprobe_multi_pid_filter * skel ;
9921008
9931009 skel = uprobe_multi_pid_filter__open_and_load ();
9941010 if (!ASSERT_OK_PTR (skel , "uprobe_multi_pid_filter__open_and_load" ))
9951011 return ;
9961012
997- run_pid_filter (skel , false);
998- run_pid_filter (skel , true);
1013+ run_pid_filter (skel , clone_vm , false);
1014+ run_pid_filter (skel , clone_vm , true);
9991015
10001016 uprobe_multi_pid_filter__destroy (skel );
10011017}
@@ -1093,5 +1109,7 @@ void test_uprobe_multi_test(void)
10931109 if (test__start_subtest ("consumers" ))
10941110 test_consumers ();
10951111 if (test__start_subtest ("filter_fork" ))
1096- test_pid_filter_process ();
1112+ test_pid_filter_process (false);
1113+ if (test__start_subtest ("filter_clone_vm" ))
1114+ test_pid_filter_process (true);
10971115}
0 commit comments