unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#36609: 27.0.50; Possible race-condition in threading implementation
@ 2019-07-11 20:51 Andreas Politz
  2019-07-12  7:47 ` Eli Zaretskii
                   ` (3 more replies)
  0 siblings, 4 replies; 53+ messages in thread
From: Andreas Politz @ 2019-07-11 20:51 UTC (permalink / raw)
  To: 36609

[-- Attachment #1: Type: text/plain, Size: 22047 bytes --]


I think there is a race-condition in the implementation of threads.  I
tried to find a minimal test-case, without success.  Thus, I've attached
a lengthy source-file.  Loading that file should trigger this bug and
may freeze your session.  

Indications:

1. The main-thread has the name of one of created threads (XEmacs in
   this case), instead of "emacs".

2. Emacs stops processing all keyboard/mouse input while looping in
   wait_reading_process_output.  Sending commands via emacsclient still
   works.

GDB output:

(gdb) info threads
  Id   Target Id                                        Frame 
* 1    Thread 0x7ffff17f5d40 (LWP 26264) "XEmacs"       0x000055555576eac0 in XPNTR (a=XIL(0x7ffff1312533)) at alloc.c:535
  2    Thread 0x7ffff0ac4700 (LWP 26265) "gmain"        0x00007ffff50d1667 in poll () from /usr/lib/libc.so.6
  3    Thread 0x7fffebd1a700 (LWP 26266) "gdbus"        0x00007ffff50d1667 in poll () from /usr/lib/libc.so.6
  4    Thread 0x7fffeb519700 (LWP 26267) "dconf worker" 0x00007ffff50d1667 in poll () from /usr/lib/libc.so.6

(gdb) bt full
#0  0x00007ffff50d3f76 in pselect () at /usr/lib/libc.so.6
#1  0x0000555555832e48 in really_call_select (arg=0x7fffffffd150) at thread.c:586
        sa = 0x7fffffffd150
        self = 0x555555c154e0 <main_thread>
        oldset = {
          __val = {0, 93825011232085, 140737488343064, 31632, 31632, 51840, 140737488343136, 93824994672716, 4294967298, 140737488343184, 93824999850720, 0, 0, 140737488343136, 93824993869565, 4041340661}
        }
#2  0x0000555555774449 in flush_stack_call_func (func=0x555555832d81 <really_call_select>, arg=0x7fffffffd150) at alloc.c:4969
        end = 0x7fffffffd100
        self = 0x555555c154e0 <main_thread>
        sentry = {
          o = {
            __max_align_ll = 140737488343296, 
            __max_align_ld = <invalid float value>
          }
        }
#3  0x0000555555832f40 in thread_select (func=0x7ffff50d3eb0 <pselect>, max_fds=6, rfds=0x7fffffffd260, wfds=0x7fffffffd2e0, efds=0x0, timeout=0x7fffffffd8b0, sigmask=0x0) at thread.c:616
        sa = {
          func = 0x7ffff50d3eb0 <pselect>, 
          max_fds = 6, 
          rfds = 0x7fffffffd260, 
          wfds = 0x7fffffffd2e0, 
          efds = 0x0, 
          timeout = 0x7fffffffd8b0, 
          sigmask = 0x0, 
          result = 210347336
        }
#4  0x000055555585fea3 in xg_select (fds_lim=6, rfds=0x7fffffffd920, wfds=0x7fffffffd9a0, efds=0x0, timeout=0x7fffffffd8b0, sigmask=0x0) at xgselect.c:117
        all_rfds = {
          fds_bits = {32, 0 <repeats 15 times>}
        }
        all_wfds = {
          fds_bits = {0 <repeats 16 times>}
        }
        tmo = {
          tv_sec = 7, 
          tv_nsec = 140737488343264
        }
        tmop = 0x7fffffffd8b0
        context = 0x555555dae320
        have_wfds = true
        gfds_buf = {{
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 32, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 7, 
            events = 0, 
            revents = 0
          }, {
            fd = 8, 
            events = 0, 
            revents = 0
          }, {
            fd = 15, 
            events = 0, 
            revents = 0
          }, {
            fd = -11072, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1460278864, 
            events = 21845, 
            revents = 0
          }, {
            fd = 64, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 2, 
            events = 48, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 91, 
            events = 124, 
            revents = 0
          }, {
            fd = -397131776, 
            events = 35414, 
            revents = 11125
          }, {
            fd = 1460278864, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1, 
            events = 0, 
            revents = 0
          }, {
            fd = 2, 
            events = 0, 
            revents = 0
          }, {
            fd = -11072, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = -11024, 
            events = 32767, 
            revents = 0
          }, {
            fd = -11088, 
            events = 32767, 
            revents = 0
          }, {
            fd = -182671191, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1, 
            events = 0, 
            revents = 0
          }, {
            fd = -182670875, 
            events = 32767, 
            revents = 0
          }, {
            fd = 194871296, 
            events = 59160, 
            revents = 48198
          }, {
            fd = -1175563804, 
            events = 19, 
            revents = 0
          }, {
            fd = 24, 
            events = 0, 
            revents = 0
          }, {
            fd = 1460278864, 
            events = 21845, 
            revents = 0
          }, {
            fd = 2, 
            events = 0, 
            revents = 0
          }, {
            fd = 1439882448, 
            events = 21845, 
            revents = 0
          }, {
            fd = 2, 
            events = 0, 
            revents = 0
          }, {
            fd = 2, 
            events = 0, 
            revents = 0
          }, {
            fd = 1, 
            events = 2, 
            revents = 0
          }, {
            fd = 1460278864, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = -397131776, 
            events = 35414, 
            revents = 11125
          }, {
            fd = 24, 
            events = 0, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = 2, 
            events = 0, 
            revents = 0
          }, {
            fd = 1, 
            events = 0, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = -182606722, 
            events = 32767, 
            revents = 0
          }, {
            fd = -10960, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1433487750, 
            events = 21845, 
            revents = 0
          }, {
            fd = -10976, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = -30, 
            events = 0, 
            revents = 0
          }, {
            fd = 1, 
            events = 0, 
            revents = 0
          }, {
            fd = 1, 
            events = 64, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 31, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = -10960, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1434542700, 
            events = 21845, 
            revents = 0
          }, {
            fd = -10912, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = -397131776, 
            events = 35414, 
            revents = 11125
          }, {
            fd = -10848, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1434543288, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1460274293, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1385447426, 
            events = 931, 
            revents = 0
          }, {
            fd = 95390, 
            events = 0, 
            revents = 0
          }, {
            fd = 1433865373, 
            events = 7256, 
            revents = 10134
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 1439161536, 
            events = 21845, 
            revents = 0
          }, {
            fd = 664149, 
            events = 0, 
            revents = 0
          }, {
            fd = 80000, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 664149080, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 664149080, 
            events = 0, 
            revents = 0
          }, {
            fd = -10752, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1434543494, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = -10544, 
            events = 32767, 
            revents = 0
          }, {
            fd = 499622378, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 499622378, 
            events = 0, 
            revents = 0
          }, {
            fd = -10688, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1434939197, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 164526702, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 664149080, 
            events = 0, 
            revents = 0
          }, {
            fd = -10544, 
            events = 32767, 
            revents = 0
          }, {
            fd = 499622378, 
            events = 41450, 
            revents = 7623
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = -1, 
            events = 65535, 
            revents = 65535
          }, {
            fd = -10432, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1433359581, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 1443725184, 
            events = 85, 
            revents = 0
          }, {
            fd = 1450650965, 
            events = 21845, 
            revents = 0
          }, {
            fd = 1450650965, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 16384, 
            events = 0, 
            revents = 0
          }, {
            fd = 5, 
            events = 0, 
            revents = 0
          }, {
            fd = -10496, 
            events = 32767, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = -1, 
            events = 65535, 
            revents = 65535
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 164526702, 
            events = 0, 
            revents = 0
          }, {
            fd = 719, 
            events = 0, 
            revents = 0
          }, {
            fd = 893997157, 
            events = 0, 
            revents = 0
          }, {
            fd = 1439269600, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = -10496, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1433288445, 
            events = 21845, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 164532384, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562977925, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562977925, 
            events = 0, 
            revents = 0
          }, {
            fd = 164532384, 
            events = 0, 
            revents = 0
          }, {
            fd = -10368, 
            events = 32767, 
            revents = 0
          }, {
            fd = 1434938909, 
            events = 21845, 
            revents = 0
          }, {
            fd = 100000, 
            events = 0, 
            revents = 0
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }, {
            fd = 1562877925, 
            events = 0, 
            revents = 0
          }, {
            fd = 164532384, 
            events = 0, 
            revents = 0
          }, {
            fd = -1, 
            events = 65535, 
            revents = 65535
          }, {
            fd = 0, 
            events = 0, 
            revents = 0
          }}
        gfds = 0x7fffffffd360
        gfds_size = 128
        n_gfds = -1
        retval = 0
        our_fds = 0
        max_fds = 5
        context_acquired = false
        i = 0
        nfds = 135
        tmo_in_millisec = 1030
        must_free = 0
        need_to_dispatch = false
#5  0x0000555555802a78 in wait_reading_process_output (time_limit=0, nsecs=0, read_kbd=-1, do_display=true, wait_for_cell=XIL(0), wait_proc=0x0, just_wait_proc=0) at process.c:5423
        process_skipped = false
        channel = 6
        nfds = 1
        Available = {
          fds_bits = {32, 0 <repeats 15 times>}
        }
        Writeok = {
          fds_bits = {0 <repeats 16 times>}
        }
        check_write = true
        check_delay = 0
        no_avail = false
        xerrno = 11
        proc = XIL(0x7fffffffd9a0)
        timeout = {
          tv_sec = 0, 
          tv_nsec = 499622378
        }
        end_time = {
          tv_sec = 93824993869565, 
          tv_nsec = 0
        }
        timer_delay = {
          tv_sec = 0, 
          tv_nsec = 499622378
        }
        got_output_end_time = {
          tv_sec = 1562977205, 
          tv_nsec = 270561059
        }
        wait = FOREVER
        got_some_output = -1
        prev_wait_proc_nbytes_read = 0
        retry_for_async = false
        count = 4
        now = {
          tv_sec = 0, 
          tv_nsec = -1
        }
#6  0x00005555556f4718 in kbd_buffer_get_event (kbp=0x7fffffffdc70, used_mouse_menu=0x7fffffffe235, end_time=0x0) at keyboard.c:3836
        do_display = true
        obj = make_fixnum(1073741816)
#7  0x00005555556f06c5 in read_event_from_main_queue (end_time=0x0, local_getcjmp=0x7fffffffe040, used_mouse_menu=0x7fffffffe235) at keyboard.c:2138
        c = XIL(0)
        save_jump = {{
            __jmpbuf = {0, 0, 0, 0, 0, 0, 0, 0}, 
            __mask_was_saved = 0, 
            __saved_mask = {
              __val = {0 <repeats 16 times>}
            }
          }}
        kb = 0x7fffffffdcd0
        count = 3
#8  0x00005555556f099b in read_decoded_event_from_main_queue (end_time=0x0, local_getcjmp=0x7fffffffe040, prev_event=XIL(0), used_mouse_menu=0x7fffffffe235) at keyboard.c:2202
        nextevt = XIL(0)
        frame = 0x1dcd30d9
        terminal = 0x9
        events = {XIL(0), XIL(0x1dcd30d9), XIL(0xca80), XIL(0x2b758a56e8544000), XIL(0), XIL(0x555556772ff5), XIL(0x7fffffffde50), XIL(0x5555556f57d8), XIL(0x555555c982e0), XIL(0), XIL(0), XIL(0x7fffffffde50), XIL(0x5555556e3efd), XIL(0x1dcd30d9), XIL(0x7fffffffde90), XIL(0x5555556f3b29)}
        n = 0
#9  0x00005555556f2236 in read_char (commandflag=1, map=XIL(0x5555567756e3), prev_event=XIL(0), used_mouse_menu=0x7fffffffe235, end_time=0x0) at keyboard.c:2810
        c = XIL(0)
        jmpcount = 3
        local_getcjmp = {{
            __jmpbuf = {0, -245616553674816983, 93825011232757, 51840, 0, 0, -245616553305718231, -6214351577293929943}, 
            __mask_was_saved = 0, 
            __saved_mask = {
              __val = {0, 0, 140737488347312, 93824993869565, 0, 140737488347424, 93824994673374, 93825011242707, 3, 0, 0, 140737488347424, 93824994446493, 93824999850720, 0, 0}
            }
          }}
        save_jump = {{
            __jmpbuf = {93824993869565, 0, 140737488347584, 93824994020698, 0, 51840, -1, 0}, 
            __mask_was_saved = 1450661587, 
            __saved_mask = {
              __val = {93825011242723, 140737488347520, 93824993870282, 93825011242707, 93825011242723, 140737488347584, 93824994446493, 93824999885184, 34464, 34464, 140737488347584, 93824993869565, 40105367251, 93825004306304, 140737488347624, 93824999850720}
            }
          }}
        tem = XIL(0x2aaa9b29c970)
        save = XIL(0)
        previous_echo_area_message = XIL(0)
        also_record = XIL(0)
        reread = false
        recorded = false
        polling_stopped_here = true
        orig_kboard = 0x555555dfa570
#10 0x00005555556ff6c8 in read_key_sequence (keybuf=0x7fffffffe440, prompt=XIL(0), dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false) at keyboard.c:9124
        interrupted_kboard = 0x555555dfa570
        interrupted_frame = 0x5555560d7f80
        key = XIL(0x5555557a7eff)
        used_mouse_menu = false
        echo_local_start = 0
        last_real_key_start = 0
        keys_local_start = 0
        new_binding = XIL(0x7fffffffe310)
        count = 3
        t = 0
        echo_start = 0
        keys_start = 0
        current_binding = XIL(0x5555567756e3)
        first_unbound = 31
        mock_input = 0
        used_mouse_menu_history = {false <repeats 30 times>}
        fkey = {
          parent = XIL(0x555555d6ce03), 
          map = XIL(0x555555d6ce03), 
          start = 0, 
          end = 0
        }
        keytran = {
          parent = XIL(0x7ffff14a7dbb), 
          map = XIL(0x7ffff14a7dbb), 
          start = 0, 
          end = 0
        }
        indec = {
          parent = XIL(0x555555d6cdf3), 
          map = XIL(0x555555d6cdf3), 
          start = 0, 
          end = 0
        }
        shift_translated = false
        delayed_switch_frame = XIL(0)
        original_uppercase = XIL(0)
        original_uppercase_position = -1
        dummyflag = false
        starting_buffer = 0x7ffff0e1f6f0
        fake_prefixed_keys = XIL(0)
        first_event = XIL(0)
        second_event = XIL(0)
#11 0x00005555556ee5fb in command_loop_1 () at keyboard.c:1348
        cmd = XIL(0)
        keybuf = {XIL(0x7fffffffe490), XIL(0x5555557a804c), make_fixnum(11545945833472), XIL(0x7fffffffe4c0), XIL(0x555555c982e0), XIL(0), XIL(0), XIL(0x7fffffffe490), XIL(0x5555556e3efd), XIL(0xf0e1f6f5), XIL(0x7fffffffe500), make_fixnum(23456248668343), XIL(0x555555d18953), XIL(0x3), XIL(0x555555c982e0), XIL(0), XIL(0), XIL(0x7fffffffe4e0), XIL(0x5555556e3efd), XIL(0xf0e1f6f5), XIL(0x7fffffffe520), XIL(0x5555557a2e69), XIL(0x1556e3efd), XIL(0x5760), XIL(0x7fffffffe540), XIL(0x555555d53470), XIL(0), XIL(0), XIL(0x7fffffffe550), make_fixnum(23456248662876)}
        i = 32767
        prev_modiff = 0
        prev_buffer = 0x0
        already_adjusted = false
#12 0x00005555557a2a64 in internal_condition_case (bfun=0x5555556ee1b3 <command_loop_1>, handlers=XIL(0x5760), hfun=0x5555556ed968 <cmd_error>) at eval.c:1351
        val = XIL(0x5555556e3efd)
        c = 0x555555d53470
#13 0x00005555556ede9b in command_loop_2 (ignore=XIL(0)) at keyboard.c:1091
        val = XIL(0)
#14 0x00005555557a22d5 in internal_catch (tag=XIL(0xd110), func=0x5555556ede6e <command_loop_2>, arg=XIL(0)) at eval.c:1112
        val = XIL(0x45b00000000)
        c = 0x555555d53340
#15 0x00005555556ede39 in command_loop () at keyboard.c:1070
#16 0x00005555556ed537 in recursive_edit_1 () at keyboard.c:714
        count = 1
        val = make_fixnum(23456248667937)
#17 0x00005555556ed6bb in Frecursive_edit () at keyboard.c:786
        count = 0
        buffer = XIL(0)
#18 0x00005555556eb49d in main (argc=4, argv=0x7fffffffe8b8) at emacs.c:2086
        stack_bottom_variable = 0x20
        do_initial_setlocale = true
        no_loadup = false
        junk = 0x0
        dname_arg = 0x0
        ch_to_dir = 0x0
        original_pwd = 0x0
        dump_mode = 0x0
        skip_args = 0
        temacs = 0x0
        attempt_load_pdump = true
        rlim = {
          rlim_cur = 10022912, 
          rlim_max = 18446744073709551615
        }
        sockfd = -1


[-- Attachment #2: thread-bug-2.el --]
[-- Type: text/plain, Size: 6199 bytes --]

;; -*- lexical-binding: t -*-

(require 'threads)
(require 'eieio)
(require 'cl-lib)
(require 'ring)

(defun debug (fmt &rest args)
  (princ (apply #'format fmt args) #'external-debugging-output)
  (terpri #'external-debugging-output))

(define-error 'thread-utils-thread-interrupted
  "Thread was interrupted" 'error)

(defun thread-utils-main-thread-p (&optional object)
  (let ((object (or object (current-thread))))
    (and (threadp object)
         (eq object (car (all-threads))))))

(defun thread-utils-quitable-apply (fn &rest args)
  (let* ((this-thread (current-thread))
         (quit-thread
          (make-thread
           (lambda nil
             (condition-case nil
                 (cl-loop (sleep-for 3))
               (quit
                (thread-signal this-thread 'quit nil))
               (thread-utils-thread-interrupted nil))))))
    (unwind-protect
        (apply fn args)
      (thread-signal
       quit-thread 'thread-utils-thread-interrupted nil))))

(defun thread-utils-condition-quitable-wait (condition)
  (cl-check-type condition condition-variable)
  (thread-utils-quitable-apply #'condition-wait condition))

(defun thread-utils-condition-wait (condition)
  (if (thread-utils-main-thread-p)
      (thread-utils-condition-quitable-wait condition)
    (condition-wait condition)))

(defconst channel-default-capacity 16)

(defclass channel-terminal nil
  ((mutex :initarg :mutex :type mutex)
   (condition :initarg :condition :type condition-variable)
   (msg-queue :initarg :msg-queue :type ring)
   (closed-p :initform nil)
   (other-terminal :type (or null channel-terminal))))

(defclass channel-source (channel-terminal) nil)
(defclass channel-sink (channel-terminal) nil)

(define-error 'channel-closed
  "Trying to send/recv from a closed channel")

(defun make-channel (&optional capacity)
  (unless capacity
    (setq capacity channel-default-capacity))
  (cl-check-type capacity (integer 1 *))
  (let* ((mutex (make-mutex "channel"))
         (condition (make-condition-variable mutex "channel"))
         (msg-queue (make-ring capacity))
         (source
          (channel-source :mutex mutex
                          :condition condition
                          :msg-queue msg-queue))
         (sink
          (channel-sink :mutex mutex
                        :condition condition
                        :msg-queue msg-queue)))
    (oset source other-terminal sink)
    (oset sink other-terminal source)
    (cons source sink)))

(cl-defgeneric channel-send ((source channel-source) message)
  (with-mutex (oref source mutex)
    (with-slots (condition msg-queue) source
      (while (and (not (channel-closed-p source))
                  (= (ring-size msg-queue)
                     (ring-length msg-queue)))
        (thread-utils-condition-wait condition))
      (when (channel-closed-p source)
        (signal 'channel-closed (list source)))
      (let ((inhibit-quit t))
        (ring-insert msg-queue message)
        (when (= 1 (ring-length msg-queue))
          (condition-notify condition t)))
      nil)))

(cl-defgeneric channel-recv ((sink channel-terminal))
  (with-mutex (oref sink mutex)
    (with-slots (condition msg-queue) sink
      (while (and (not (channel-closed-p sink))
                  (ring-empty-p msg-queue))
        (thread-utils-condition-wait condition))
      (when (channel-closed-p sink)
        (signal 'channel-closed (list sink)))
      (let ((inhibit-quit t))
        (prog1 (ring-remove msg-queue)
          (when (= 1 (- (ring-size msg-queue)
                        (ring-length msg-queue)))
            (condition-notify condition t)))))))

(cl-defgeneric channel-peek ((sink channel-terminal))
  (with-mutex (oref sink mutex)
    (with-slots (condition msg-queue) sink
      (while (and (not (channel-closed-p sink))
                  (ring-empty-p msg-queue))
        (thread-utils-condition-wait condition))
      (when (channel-closed-p sink)
        (signal 'channel-closed (list sink)))
      (ring-ref msg-queue -1))))

(cl-defgeneric channel-close ((terminal channel-terminal))
  (with-mutex (oref terminal mutex)
    (with-slots (closed-p condition) terminal
      (setq closed-p t)
      (condition-notify condition t))
    nil))

(cl-defmethod channel-closed-p ((source channel-source))

  (with-mutex (oref source mutex)
    (with-slots (closed-p other-terminal) source
      (or closed-p
          (oref other-terminal closed-p)))))

(cl-defmethod channel-closed-p ((sink channel-sink))
  (with-mutex (oref sink mutex)
    (with-slots (closed-p other-terminal msg-queue) sink
      (or closed-p
          (and (oref other-terminal closed-p)
               (ring-empty-p msg-queue))))))

(defclass future nil
  ((channel :initform (make-channel 1))))

(defun make-future ()
  (make-instance 'future))

(cl-defgeneric future-set ((future future) value)
  (with-slots (channel) future
    (let ((inhibit-quit t))
      (condition-case nil
          (progn
            (debug "Sending future")
            (channel-send (car channel) value)
            (debug "Future send"))
        (channel-closed
         (signal 'error (list future))))
      (debug "Closing future")
      (channel-close (car channel))
      (debug "Future closed"))))

(cl-defgeneric future-get ((future future))
  (with-slots (channel) future
    (debug "Getting future")
    (channel-peek (cdr channel))
    (debug "Future got")))

(defclass future-deferred (future)
  ((producer :initarg :producer :type function)
   (value-produced-p :initform nil)
   (mutex :initform (make-mutex "future-deferred"))))

(defun make-deferred-future (producer)
  (make-instance 'future-deferred :producer producer))

(cl-defmethod future-get :before ((future future-deferred))
  (with-slots (mutex value-produced-p producer) future
    (with-mutex mutex
      (unless value-produced-p
        (unwind-protect
            (make-thread
             (lambda nil
               (debug "Setting Future")
               (future-set future (funcall producer))
               (debug "Future set"))
             "XEmacs")
          (setq value-produced-p t))))))

(let ((future (make-deferred-future (lambda nil 42))))
  (future-get future))

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2021-06-25 13:54 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-07-11 20:51 bug#36609: 27.0.50; Possible race-condition in threading implementation Andreas Politz
2019-07-12  7:47 ` Eli Zaretskii
2019-07-12  8:05   ` Eli Zaretskii
2019-07-12  9:02 ` Pip Cet
2019-07-12 12:42   ` Eli Zaretskii
2019-07-12 12:57     ` Pip Cet
2019-07-12 13:31       ` Eli Zaretskii
2019-07-12 13:51         ` Pip Cet
2019-07-12 15:05           ` Eli Zaretskii
2019-07-12 18:06             ` Pip Cet
2019-07-12 18:27               ` Eli Zaretskii
2019-07-12 18:34                 ` Eli Zaretskii
2019-07-12 19:24                   ` Pip Cet
2019-07-12 19:57                     ` Eli Zaretskii
2019-07-13 14:37                       ` Pip Cet
2019-07-13 15:03                         ` Eli Zaretskii
2019-07-13 15:13                           ` Eli Zaretskii
2019-07-13 15:54                           ` Eli Zaretskii
2019-07-13 15:57                             ` Pip Cet
2019-07-13 16:02                               ` Eli Zaretskii
2019-07-13 18:17                                 ` Pip Cet
2020-08-21 12:57                                   ` Lars Ingebrigtsen
2019-07-13 15:04                         ` Andreas Politz
2019-07-12 12:44   ` Pip Cet
2019-07-12 12:55     ` Eli Zaretskii
2019-07-12 13:40       ` Pip Cet
2019-07-12 13:51         ` Eli Zaretskii
2019-07-12 14:34           ` Pip Cet
2019-07-12 15:02             ` Eli Zaretskii
2019-07-12 19:30               ` Pip Cet
2019-07-13  6:50                 ` Eli Zaretskii
2021-06-06 15:50 ` dick.r.chiang
     [not found] ` <87fsxv8182.fsf@dick>
2021-06-06 16:35   ` Eli Zaretskii
2021-06-06 19:10     ` dick.r.chiang
2021-06-06 19:27       ` Eli Zaretskii
2021-06-09 21:40         ` dick.r.chiang
2021-06-10  6:46           ` Eli Zaretskii
2021-06-10 11:52             ` dick.r.chiang
2021-06-10 14:18               ` Eli Zaretskii
2021-06-10 14:55                 ` dick.r.chiang
2021-06-10 15:04                   ` Eli Zaretskii
2021-06-10 21:36                     ` dick.r.chiang
2021-06-11  6:00                       ` Eli Zaretskii
2021-06-19 17:53                         ` Eli Zaretskii
2021-06-19 19:14                           ` dick.r.chiang
2021-06-19 19:18                             ` Eli Zaretskii
2021-06-19 21:12                               ` dick.r.chiang
2021-06-20 11:39                                 ` Eli Zaretskii
2021-06-20 14:01                                   ` dick.r.chiang
2021-06-20 15:53                                     ` Eli Zaretskii
2021-06-25 13:54                                       ` Eli Zaretskii
2021-06-10 15:35                 ` Andreas Schwab
2021-06-10 15:39                   ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).