Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when inheriting from class in unit syntax #20890

Open
johannessen opened this issue Mar 2, 2023 · 6 comments
Open

Segfault when inheriting from class in unit syntax #20890

johannessen opened this issue Mar 2, 2023 · 6 comments

Comments

@johannessen
Copy link
Contributor

Description

A class declared in the “unit” (or “statement”) syntax – i. e. not with a block – cannot be used as the superclass of another class. A segmentation fault occurs when this is attempted. This happens with v5.37.9 as well as blead at 49830b9 (HEAD at time of this writing). The following combination triggers the bug:

class A;
class B :isa(A) { }

(The diagnostics generated by my OS include a stack trace and are appended at the end of this report.)

Steps to Reproduce

perl -Mfeature=class -e 'class A; class B :isa(A) {}'

Expected behaviour

Clean exit.

Perl configuration

Summary of my perl5 (revision 5 version 37 subversion 10) configuration:
  Commit id: 49830b9d6df254629bb26062f7477b3b371dd1d2
  Platform:
    osname=darwin
    osvers=19.6.0
    archname=darwin-2level
    uname='darwin solway.local 19.6.0 darwin kernel version 19.6.0: tue jun 21 21:18:39 pdt 2022; root:xnu-6153.141.66~1release_x86_64 x86_64 '
    config_args='-des -Doptimize=-g -Dusedevel'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
  Compiler:
    cc='cc'
    ccflags ='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    optimize='-g'
    cppflags='-fno-common -DPERL_DARWIN -mmacosx-version-min=10.15 -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='Apple LLVM 12.0.0 (clang-1200.0.32.27)'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -mmacosx-version-min=10.15 -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /Library/Developer/CommandLineTools/usr/lib/clang/12.0.0/lib /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/lib /Library/Developer/CommandLineTools/usr/lib /usr/lib
    libs=-lpthread -lgdbm -ldbm -ldl -lm -lutil -lc
    perllibs=-lpthread -ldl -lm -lutil -lc
    libc=
    so=dylib
    useshrplib=false
    libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=bundle
    d_dlsymun=undef
    ccdlflags=' '
    cccdlflags=' '
    lddlflags=' -mmacosx-version-min=10.15 -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector-strong'


Characteristics of this binary (from libperl): 
  Compile-time options:
    HAS_TIMES
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_HASH_FUNC_SIPHASH13
    PERL_HASH_USE_SBOX32
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_DEVEL
    PERL_USE_SAFE_PUTENV
    USE_64_BIT_ALL
    USE_64_BIT_INT
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
  Built under darwin
  Compiled at Mar  2 2023 17:22:56
  %ENV:
    PERLBREW_HOME="/Users/aj/.perlbrew"
    PERLBREW_PATH="/Users/aj/.perlbrew/bin"
    PERLBREW_ROOT="/Users/aj/.perlbrew"
    PERLBREW_SHELLRC_VERSION="0.92"
    PERLBREW_VERSION="0.92"
    PERL_CPANM_OPT="--from https://www.cpan.org/"
  @INC:
    /usr/local/lib/perl5/site_perl/5.37.10/darwin-2level
    /usr/local/lib/perl5/site_perl/5.37.10
    /usr/local/lib/perl5/5.37.10/darwin-2level
    /usr/local/lib/perl5/5.37.10

Diagnostic report

Process:               perl5.37.10 [18673]
Path:                  /usr/local/bin/perl5.37.10
Identifier:            perl5.37.10
Version:               0
Code Type:             X86-64 (Native)
Parent Process:        bash [17374]
Responsible:           Terminal [394]
User ID:               501

Date/Time:             2023-03-02 17:29:06.974 +0100
OS Version:            Mac OS X 10.15.7 (19H2026)
Report Version:        12
Bridge OS Version:     6.6 (19P6064)
Anonymous UUID:        BD30FBD8-DA90-50A6-237D-82B109CD6C8C

Sleep/Wake UUID:       C53EDE24-E6C8-4814-A46A-F0771E7FD0D5

Time Awake Since Boot: 600000 seconds
Time Since Wake:       2700 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x000000000000000c
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [18673]

VM Regions Near 0xc:
--> 
    __TEXT                 000000010460a000-0000000104a42000 [ 4320K] r-x/r-x SM=COW  /usr/local/bin/perl5.37.10

Application Specific Information:
dyld2 mode

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   perl5.37.10                   	0x00000001046392f8 Perl_ck_svconst + 24 (op.c:14658)
1   perl5.37.10                   	0x000000010461578c Perl_newSVOP + 348 (op.c:7582)
2   perl5.37.10                   	0x00000001047a6ef2 Perl_class_seal_stash + 690 (class.c:690)
3   perl5.37.10                   	0x00000001047a69a8 invoke_class_seal + 24 (class.c:316)
4   perl5.37.10                   	0x00000001048215ce Perl_leave_scope + 5198 (scope.c:1494)
5   perl5.37.10                   	0x000000010461a3ca Perl_block_end + 586 (op.c:4526)
6   perl5.37.10                   	0x00000001046a4828 Perl_yyparse + 6424 (perly.y:620)
7   perl5.37.10                   	0x0000000104643f4d S_parse_body + 4445 (perl.c:2608)
8   perl5.37.10                   	0x0000000104642209 perl_parse + 1849 (perl.c:1917)
9   perl5.37.10                   	0x000000010460b373 main + 163 (perlmain.c:106)
10  libdyld.dylib                 	0x00007fff68d72cc9 start + 1

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x0000000000000000  rcx: 0x00007fbe42c17498  rdx: 0x0000000000000000
  rdi: 0x00007fbe42c17498  rsi: 0x000000000000ffc7  rbp: 0x00007ffeeb5f4800  rsp: 0x00007ffeeb5f4800
   r8: 0x0000000000000004   r9: 0x00000000000005a3  r10: 0x0000000000008000  r11: 0x0000000000000080
  r12: 0x0000000000000000  r13: 0x0000000000000000  r14: 0x0000000000000000  r15: 0x0000000000000000
  rip: 0x00000001046392f8  rfl: 0x0000000000010246  cr2: 0x000000000000000c
  
Logical CPU:     0
Error Code:      0x00000004 (no mapping for user data read)
Trap Number:     14


Binary Images:
       0x10460a000 -        0x104a41fff +perl5.37.10 (0) <59993232-1A5D-3D47-8285-82020035316C> /usr/local/bin/perl5.37.10
       0x10e3e6000 -        0x10e478267  dyld (750.7) <9F48F7F8-94D0-3793-99B7-DDEF657EF956> /usr/lib/dyld
    0x7fff65d55000 -     0x7fff65d56fff  libSystem.B.dylib (1281.100.1) <5A20AE6C-BF4D-3689-B7D2-19F0721F6375> /usr/lib/libSystem.B.dylib
    0x7fff6603b000 -     0x7fff6608dfff  libc++.1.dylib (902.1) <59A8239F-C28A-3B59-B8FA-11340DC85EDC> /usr/lib/libc++.1.dylib
    0x7fff6608e000 -     0x7fff660a3ffb  libc++abi.dylib (902) <E692F14F-C65E-303B-9921-BB7E97D77855> /usr/lib/libc++abi.dylib
    0x7fff67bb7000 -     0x7fff67beafde  libobjc.A.dylib (787.1) <6DF81160-5E7F-3E31-AA1E-C875E3B98AF6> /usr/lib/libobjc.A.dylib
    0x7fff6816d000 -     0x7fff68170ffb  libutil.dylib (57.140.1) <6EC380B0-FBB1-3AE3-8A09-1851E128C70F> /usr/lib/libutil.dylib
    0x7fff68b54000 -     0x7fff68b59ff3  libcache.dylib (83) <AF488D13-9E89-35E0-B078-BE37CC5B8586> /usr/lib/system/libcache.dylib
    0x7fff68b5a000 -     0x7fff68b65fff  libcommonCrypto.dylib (60165.120.1) <C7912BE5-993E-3581-B2A0-6AABDC8C5562> /usr/lib/system/libcommonCrypto.dylib
    0x7fff68b66000 -     0x7fff68b6dfff  libcompiler_rt.dylib (101.2) <49B8F644-5705-3F16-BBE0-6FFF9B17C36E> /usr/lib/system/libcompiler_rt.dylib
    0x7fff68b6e000 -     0x7fff68b77ff7  libcopyfile.dylib (166.40.1) <3C481225-21E7-370A-A30E-0CCFDD64A92C> /usr/lib/system/libcopyfile.dylib
    0x7fff68b78000 -     0x7fff68c0afdb  libcorecrypto.dylib (866.140.2) <E9AAA2A6-D0D4-328A-BEA2-4DC5E513BA30> /usr/lib/system/libcorecrypto.dylib
    0x7fff68d17000 -     0x7fff68d57ff0  libdispatch.dylib (1173.100.2) <CD9C059C-91D9-30E8-8926-5B9CD0D5D4F5> /usr/lib/system/libdispatch.dylib
    0x7fff68d58000 -     0x7fff68d8efff  libdyld.dylib (750.7) <AB99C9EE-7127-3451-89AB-339F8F2CEE61> /usr/lib/system/libdyld.dylib
    0x7fff68d8f000 -     0x7fff68d8fffb  libkeymgr.dylib (30) <DB3337BE-01CA-3425-BD0C-87774FC0CDC0> /usr/lib/system/libkeymgr.dylib
    0x7fff68d9d000 -     0x7fff68d9dff7  liblaunch.dylib (1738.140.3) <E2CFD17D-F36C-3734-8F37-16798799EF9E> /usr/lib/system/liblaunch.dylib
    0x7fff68d9e000 -     0x7fff68da3ff7  libmacho.dylib (959.0.1) <AA613A9C-961A-3B67-B696-4622FA59FC4E> /usr/lib/system/libmacho.dylib
    0x7fff68da4000 -     0x7fff68da6ff3  libquarantine.dylib (110.40.6) <6CADF28C-2F20-3FA5-9FB9-49EAB0FD2489> /usr/lib/system/libquarantine.dylib
    0x7fff68da7000 -     0x7fff68da8ff7  libremovefile.dylib (48) <7C7EFC79-BD24-33EF-B073-06AED234593E> /usr/lib/system/libremovefile.dylib
    0x7fff68da9000 -     0x7fff68dc0ff3  libsystem_asl.dylib (377.60.4) <BDE4E1E6-BB8F-3EAC-A9CD-53B9FBD96554> /usr/lib/system/libsystem_asl.dylib
    0x7fff68dc1000 -     0x7fff68dc1ff7  libsystem_blocks.dylib (74) <0D53847E-AF5F-3ACF-B51F-A15DEA4DEC58> /usr/lib/system/libsystem_blocks.dylib
    0x7fff68dc2000 -     0x7fff68e49fff  libsystem_c.dylib (1353.100.4) <BCD3F031-4A3F-32CF-AB9A-D6EE7A7499D4> /usr/lib/system/libsystem_c.dylib
    0x7fff68e4a000 -     0x7fff68e4dffb  libsystem_configuration.dylib (1061.141.2) <393137B7-3631-3450-B6F4-95EECD3ADDFF> /usr/lib/system/libsystem_configuration.dylib
    0x7fff68e4e000 -     0x7fff68e51fff  libsystem_coreservices.dylib (114.1) <72857ADA-AA97-398B-B089-F50B2E89064B> /usr/lib/system/libsystem_coreservices.dylib
    0x7fff68e52000 -     0x7fff68e5afff  libsystem_darwin.dylib (1353.100.4) <19242BF1-BAF6-3DF0-AAD3-93E3E0870DBE> /usr/lib/system/libsystem_darwin.dylib
    0x7fff68e5b000 -     0x7fff68e62fff  libsystem_dnssd.dylib (1096.100.3) <EBB4C2C2-E031-3094-B40A-E67BF261D295> /usr/lib/system/libsystem_dnssd.dylib
    0x7fff68e63000 -     0x7fff68e64ffb  libsystem_featureflags.dylib (17) <29FD922A-EC2C-3F25-BCCC-B58D716E60EC> /usr/lib/system/libsystem_featureflags.dylib
    0x7fff68e65000 -     0x7fff68eb2ff7  libsystem_info.dylib (538.1) <D057695A-F11C-3863-971C-EA1EBF8662B1> /usr/lib/system/libsystem_info.dylib
    0x7fff68eb3000 -     0x7fff68edfff7  libsystem_kernel.dylib (6153.141.66) <FF081F3A-F653-3F8F-9E64-9F34792EEDB3> /usr/lib/system/libsystem_kernel.dylib
    0x7fff68ee0000 -     0x7fff68f27fff  libsystem_m.dylib (3178) <00F331F1-0D09-39B3-8736-1FE90E64E903> /usr/lib/system/libsystem_m.dylib
    0x7fff68f28000 -     0x7fff68f4ffff  libsystem_malloc.dylib (283.100.6) <8549294E-4C53-36EB-99F3-584A7393D8D5> /usr/lib/system/libsystem_malloc.dylib
    0x7fff68f50000 -     0x7fff68f5dffb  libsystem_networkextension.dylib (1095.140.2) <F06C65C5-2CBE-313C-96E1-A09240F9FE57> /usr/lib/system/libsystem_networkextension.dylib
    0x7fff68f5e000 -     0x7fff68f67ff7  libsystem_notify.dylib (241.100.2) <FA22F928-D91B-3AA5-96BB-3186AC0FB264> /usr/lib/system/libsystem_notify.dylib
    0x7fff68f68000 -     0x7fff68f70fef  libsystem_platform.dylib (220.100.1) <009A7C1F-313A-318E-B9F2-30F4C06FEA5C> /usr/lib/system/libsystem_platform.dylib
    0x7fff68f71000 -     0x7fff68f7bfff  libsystem_pthread.dylib (416.100.3) <62CB1A98-0B8F-31E7-A02B-A1139927F61D> /usr/lib/system/libsystem_pthread.dylib
    0x7fff68f7c000 -     0x7fff68f80ff3  libsystem_sandbox.dylib (1217.141.9) <75C7915D-19C4-3F32-B320-394BA4B18655> /usr/lib/system/libsystem_sandbox.dylib
    0x7fff68f81000 -     0x7fff68f83fff  libsystem_secinit.dylib (62.100.2) <F80872AA-E1FD-3D7E-8729-467656EC6561> /usr/lib/system/libsystem_secinit.dylib
    0x7fff68f84000 -     0x7fff68f8bffb  libsystem_symptoms.dylib (1238.120.2) <702D0910-5C34-3D43-9631-8BD215DE4FE1> /usr/lib/system/libsystem_symptoms.dylib
    0x7fff68f8c000 -     0x7fff68fa2ff2  libsystem_trace.dylib (1147.120.1) <BC141783-66D9-3137-A783-211B38E49ADB> /usr/lib/system/libsystem_trace.dylib
    0x7fff68fa4000 -     0x7fff68fa9ff7  libunwind.dylib (35.4) <42B7B509-BAFE-365B-893A-72414C92F5BF> /usr/lib/system/libunwind.dylib
    0x7fff68faa000 -     0x7fff68fdfffe  libxpc.dylib (1738.140.3) <8DA7D88F-AE2F-3BCF-8426-8D041E57A9AA> /usr/lib/system/libxpc.dylib

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 57482115
    thread_create: 0
    thread_set_state: 0

VM Region Summary:
ReadOnly portion of Libraries: Total=393.7M resident=0K(0%) swapped_out_or_unallocated=393.7M(100%)
Writable regions: Total=145.4M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=145.4M(100%)
 
                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Kernel Alloc Once                    8K        1 
MALLOC                            17.1M        9 
MALLOC guard page                   24K        5 
MALLOC_MEDIUM (reserved)         120.0M        1         reserved VM address space (unallocated)
STACK GUARD                       56.0M        1 
Stack                             8192K        1 
__DATA                             645K       42 
__DATA_CONST                        84K        2 
__LINKEDIT                       384.9M        4 
__OBJC_RO                         32.3M        1 
__OBJC_RW                         1860K        2 
__TEXT                            9088K       41 
shared memory                        8K        2 
===========                     =======  ======= 
TOTAL                            629.7M      112 
TOTAL, minus reserved VM space   509.7M      112 
@johannessen
Copy link
Contributor Author

For what it’s worth, this seems to work fine:

{
  class A;
}
class B :isa(A) { }

 
Having the two classes in two separate .pm files also seems to work fine.

@jkeenan
Copy link
Contributor

jkeenan commented Mar 4, 2023

@leonerd, can you take a look at this problem re class? Thx.

@tonycoz
Copy link
Contributor

tonycoz commented Aug 8, 2023

The problem is the class_initfields_cv pointer (which creates the sub that initializes the class fields) isn't created until the end of scope, and in the failing case that is after the class B ....

In the non-crashing case, the {} around the class A; has an end of scope before the class B ... so the initfields CV is populated and everything works.

I'm not sure how this is intended to work, if I do a "statement" package, a block package restores the current class:

$ ./perl -Ilib -E 'package Foo; package Bar { ; } say __PACKAGE__'
Foo

but if we do that with class, as with the failing code, the documentation says the class is closed once class B is seen, from perlclass:

If the statement form is used, the remainder of the file is used up until the next C or C statement.

what should the current class/package be after the closing brace of class B? If we do close class A, then any additional fields will invalidate the initfields CV, additional methods shouldn't be such a problem, but allowing one and not the other is inconsistent:

class A;
class B :isa(A) { }
# in theory seeing "class B" sealed A, what does the following do?
method somename {} # whose method am I?
field $x; # we already sealed the class

I'd be inclined to simply disallow the statement form.

@leonerd , @Ovid any ideas?

Backtrace with debug info:

perl: op.c:7612: Perl_newSVOP: Assertion `sv' failed.

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, 
    no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, 
    signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007ffff7d30d9f in __pthread_kill_internal (signo=6, 
    threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  0x00007ffff7ce1f32 in __GI_raise (sig=sig@entry=6)
    at ../sysdeps/posix/raise.c:26
#3  0x00007ffff7ccc472 in __GI_abort () at ./stdlib/abort.c:79
#4  0x00007ffff7ccc395 in __assert_fail_base (
    fmt=0x7ffff7e40a90 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
    assertion=assertion@entry=0x55555597a281 "sv", 
    file=file@entry=0x55555597aef1 "op.c", line=line@entry=7612, 
    function=function@entry=0x555555982588 <__PRETTY_FUNCTION__.135> "Perl_newSVOP") at ./assert/assert.c:92
#5  0x00007ffff7cdae32 in __GI___assert_fail (assertion=0x55555597a281 "sv", 
    file=0x55555597aef1 "op.c", line=7612, 
    function=0x555555982588 <__PRETTY_FUNCTION__.135> "Perl_newSVOP")
    at ./assert/assert.c:101
#6  0x00005555555b8a52 in Perl_newSVOP (type=5, flags=0, sv=0x0) at op.c:7612
#7  0x00005555557bd379 in Perl_class_seal_stash (stash=0x555555c4d478)
    at class.c:690
#8  0x00005555557ba7a1 in invoke_class_seal (_arg=0x555555c4d478)
    at class.c:315
#9  0x0000555555899925 in Perl_leave_scope (base=69) at scope.c:1518
#10 0x00005555555aed95 in Perl_block_end (floor=69, seq=0x0) at op.c:4529
#11 0x0000555555679439 in Perl_yyparse (gramtype=258)
    at /home/tony/dev/perl/git/perl6/perly.y:619
#12 0x00005555555e58d3 in S_parse_body (env=0x0, 
    xsinit=0x55555559d1ff <xs_init>) at perl.c:2613
#13 0x00005555555e399b in perl_parse (my_perl=0x555555c272a0, 
    xsinit=0x55555559d1ff <xs_init>, argc=4, argv=0x7fffffffe7e8, env=0x0)
    at perl.c:1919
#14 0x000055555559d10e in main (argc=4, argv=0x7fffffffe7e8, 
    env=0x7fffffffe810) at perlmain.c:106

@johannessen
Copy link
Contributor Author

Nice find. FWIW, I think the statement form is important to have in Perl.

Consistency with package would be good. That means the following two examples should be semantically the same:

class A;
class B {}
class A {
  class B {}
}

Which means it should perhaps be a syntax error for B to inherit from A here because the declaration of A is not yet complete by the time the B :isa(A) would be encountered.

It turns out the second form causes what I expect is the exact same issue without class; statements entirely:

perl -Mfeature=class -e 'class A { class B :isa(A) {} }'
# Segmentation fault: 11

(Although I wonder if allowing class {} to nest in v5.38 might have been an oversight?)

@Ovid
Copy link
Contributor

Ovid commented Aug 8, 2023

For what it's worth, someone asked a related question on Reddit and I provided an answer, linking to this thread.

@johannessen
Copy link
Contributor Author

This still segfaults for me on v5.39.10. So do #20947 and #20956.

I think these were supposed to be listed as known bugs in perldelta for v5.38.0 / v5.38.2, but we kinda forgot.

Are these issues currently mentioned anywhere in Perl’s documentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants