Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions demo.py

This file was deleted.

10 changes: 10 additions & 0 deletions fork_map.wpr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
# Wing project file #
##################################################################
[project attributes]
console.toolbox = [{'autosave': False,
'id': 'cmd-JWEPUsuAbCaNufpa',
'io_encoding': None,
'key_binding': None,
'line_mode': True,
'loc': '/home/rutherford/code/fork_map/fork_map/demos/fork.py',
'pseudo_tty': False,
'raise_panel': True,
'shared': False,
'title': None}]
proj.directory-list = [{'dirloc': loc('fork_map'),
'excludes': (),
'filter': '*',
Expand Down
23 changes: 23 additions & 0 deletions fork_map/demos/deadlock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""The below code causes a deadlock on python <3.14"""

import os
import time
from concurrent.futures import ProcessPoolExecutor
import threading

lock = threading.Lock()


def process_items(name):
print(f"{name}: acquiring lock")
with lock:
print(f"{name}: has lock")
time.sleep(0.1)
print(f"{name}: released lock")


t = threading.Thread(target=process_items, args=("Thread",))
t.start()

with ProcessPoolExecutor() as e:
e.submit(process_items, "Process")
25 changes: 25 additions & 0 deletions fork_map/demos/demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os

# Todo fix import paths
from fork_map.fork_map import fork_map

result = fork_map(lambda x: x * 2, range(5))
print(result)

## -----------------------------------

from multiprocessing.pool import Pool

# This fails, as lambdas aren't pickleable.
# with Pool() as p:
# result = p.map(lambda x: x * 2, range(5))

# print(result)


# ----

LETTERS = "abcde"

for r in fork_map(lambda idx: f"{os.getpid()} got letter {LETTERS[idx]}", [0, 1, 3]):
print(r)
7 changes: 7 additions & 0 deletions fork_map/demos/fork.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os

pid = os.fork()
if pid:
print('I am the parent')
else:
print('I am the child')
19 changes: 19 additions & 0 deletions fork_map/demos/fork_vs_spawn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""The below fails unless start method is fork"""

import os
import multiprocessing
from concurrent.futures import ProcessPoolExecutor


def get_letter(idx: int) -> str:
pid = os.getpid()
return f"{pid=} got letter {LETTERS[idx]}"


if __name__ == "__main__":
multiprocessing.set_start_method("spawn")
LETTERS = "abcde"

with ProcessPoolExecutor() as e:
for r in e.map(get_letter, [0, 1, 3]):
print(r)
5 changes: 3 additions & 2 deletions fork_map/fork_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,13 @@ def _process_in_fork(
try:
r = func(*args, **kwargs)

# pickle here, so that we can't crash with pickle errors in the finally clause
# pickle here, so that we can't crash with pickle errors in the finally clause.
pickled_r = pickle.dumps(r)
result = make_result(result=pickled_r)
except Exception as e:
try:
# In case func does something stupid like raising an unpicklable exception
# In case func does something untoward like raising an unpicklable
# exception.
pickled_exception = pickle.dumps(e)
except AttributeError:
pickled_exception = pickle.dumps(
Expand Down