diff --git a/SOURCES/0001-IntrospectionModule-handle-two-threads-loading-type-.patch b/SOURCES/0001-IntrospectionModule-handle-two-threads-loading-type-.patch
new file mode 100644
index 0000000..d279132
--- /dev/null
+++ b/SOURCES/0001-IntrospectionModule-handle-two-threads-loading-type-.patch
@@ -0,0 +1,158 @@
+From eb791e7cca0998bc75e0b3f7e8ecf2672c96d7f8 Mon Sep 17 00:00:00 2001
+From: Ray Strode <rstrode@redhat.com>
+Date: Wed, 10 Jun 2020 18:04:07 -0400
+Subject: [PATCH] IntrospectionModule: handle two threads loading type at same
+ time
+
+If two threads are trying to load a type at exactly the same time,
+it's possible for two wrappers to get generated for the type.
+One thread will end up with the wrapper that's not blessed as the
+"real" one and future calls will fail.  The blessed wrapper will
+be incomplete, and so future calls from it will fail as well.
+
+This commit adds a lock to ensure the two threads don't stomp
+on each others toes.
+---
+ gi/module.py | 110 +++++++++++++++++++++++++++------------------------
+ 1 file changed, 58 insertions(+), 52 deletions(-)
+
+--- a/gi/module.py	2020-06-10 18:09:19.292409072 -0400
++++ b/gi/module.py	2020-06-10 18:11:24.727045466 -0400
+@@ -24,6 +24,7 @@ from __future__ import absolute_import
+ 
+ import sys
+ import importlib
++from threading import Lock
+ 
+ _have_py3 = (sys.version_info[0] >= 3)
+ 
+@@ -131,6 +132,8 @@ class IntrospectionModule(object):
+         if self._version is None:
+             self._version = repository.get_version(self._namespace)
+ 
++        self._lock = Lock()
++
+     def __getattr__(self, name):
+         info = repository.find_by_name(self._namespace, name)
+         if not info:
+@@ -139,39 +142,40 @@ class IntrospectionModule(object):
+ 
+         if isinstance(info, EnumInfo):
+             g_type = info.get_g_type()
+-            wrapper = g_type.pytype
++            with self._lock:
++                wrapper = g_type.pytype
+ 
+-            if wrapper is None:
+-                if info.is_flags():
+-                    if g_type.is_a(TYPE_FLAGS):
+-                        wrapper = flags_add(g_type)
+-                    else:
+-                        assert g_type == TYPE_NONE
+-                        wrapper = flags_register_new_gtype_and_add(info)
+-                else:
+-                    if g_type.is_a(TYPE_ENUM):
+-                        wrapper = enum_add(g_type)
++                if wrapper is None:
++                    if info.is_flags():
++                        if g_type.is_a(TYPE_FLAGS):
++                            wrapper = flags_add(g_type)
++                        else:
++                            assert g_type == TYPE_NONE
++                            wrapper = flags_register_new_gtype_and_add(info)
+                     else:
+-                        assert g_type == TYPE_NONE
+-                        wrapper = enum_register_new_gtype_and_add(info)
+-
+-                wrapper.__info__ = info
+-                wrapper.__module__ = 'gi.repository.' + info.get_namespace()
+-
+-                # Don't use upper() here to avoid locale specific
+-                # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
+-                # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
+-                ascii_upper_trans = maketrans(
+-                    'abcdefgjhijklmnopqrstuvwxyz',
+-                    'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
+-                for value_info in info.get_values():
+-                    value_name = value_info.get_name_unescaped().translate(ascii_upper_trans)
+-                    setattr(wrapper, value_name, wrapper(value_info.get_value()))
+-                for method_info in info.get_methods():
+-                    setattr(wrapper, method_info.__name__, method_info)
++                        if g_type.is_a(TYPE_ENUM):
++                            wrapper = enum_add(g_type)
++                        else:
++                            assert g_type == TYPE_NONE
++                            wrapper = enum_register_new_gtype_and_add(info)
++
++                    wrapper.__info__ = info
++                    wrapper.__module__ = 'gi.repository.' + info.get_namespace()
++
++                    # Don't use upper() here to avoid locale specific
++                    # identifier conversion (e. g. in Turkish 'i'.upper() == 'i')
++                    # see https://bugzilla.gnome.org/show_bug.cgi?id=649165
++                    ascii_upper_trans = maketrans(
++                        'abcdefgjhijklmnopqrstuvwxyz',
++                        'ABCDEFGJHIJKLMNOPQRSTUVWXYZ')
++                    for value_info in info.get_values():
++                        value_name = value_info.get_name_unescaped().translate(ascii_upper_trans)
++                        setattr(wrapper, value_name, wrapper(value_info.get_value()))
++                    for method_info in info.get_methods():
++                        setattr(wrapper, method_info.__name__, method_info)
+ 
+-            if g_type != TYPE_NONE:
+-                g_type.pytype = wrapper
++                if g_type != TYPE_NONE:
++                    g_type.pytype = wrapper
+ 
+         elif isinstance(info, RegisteredTypeInfo):
+             g_type = info.get_g_type()
+@@ -202,27 +206,28 @@ class IntrospectionModule(object):
+             else:
+                 raise NotImplementedError(info)
+ 
+-            # Check if there is already a Python wrapper that is not a parent class
+-            # of the wrapper being created. If it is a parent, it is ok to clobber
+-            # g_type.pytype with a new child class wrapper of the existing parent.
+-            # Note that the return here never occurs under normal circumstances due
+-            # to caching on the __dict__ itself.
+-            if g_type != TYPE_NONE:
+-                type_ = g_type.pytype
+-                if type_ is not None and type_ not in bases:
+-                    self.__dict__[name] = type_
+-                    return type_
+-
+-            dict_ = {
+-                '__info__': info,
+-                '__module__': 'gi.repository.' + self._namespace,
+-                '__gtype__': g_type
+-            }
+-            wrapper = metaclass(name, bases, dict_)
+-
+-            # Register the new Python wrapper.
+-            if g_type != TYPE_NONE:
+-                g_type.pytype = wrapper
++            with self._lock:
++                # Check if there is already a Python wrapper that is not a parent class
++                # of the wrapper being created. If it is a parent, it is ok to clobber
++                # g_type.pytype with a new child class wrapper of the existing parent.
++                # Note that the return here never occurs under normal circumstances due
++                # to caching on the __dict__ itself.
++                if g_type != TYPE_NONE:
++                    type_ = g_type.pytype
++                    if type_ is not None and type_ not in bases:
++                        self.__dict__[name] = type_
++                        return type_
++
++                dict_ = {
++                    '__info__': info,
++                    '__module__': 'gi.repository.' + self._namespace,
++                    '__gtype__': g_type
++                }
++                wrapper = metaclass(name, bases, dict_)
++
++                # Register the new Python wrapper.
++                if g_type != TYPE_NONE:
++                    g_type.pytype = wrapper
+ 
+         elif isinstance(info, FunctionInfo):
+             wrapper = info
diff --git a/SPECS/pygobject3.spec b/SPECS/pygobject3.spec
index f3d3437..e8cd524 100644
--- a/SPECS/pygobject3.spec
+++ b/SPECS/pygobject3.spec
@@ -10,7 +10,7 @@
 
 Name:           pygobject3
 Version:        3.28.3
-Release:        1%{?dist}
+Release:        2%{?dist}
 Summary:        Python bindings for GObject Introspection
 
 License:        LGPLv2+ and MIT
@@ -39,6 +39,8 @@ BuildRequires:  dejavu-serif-fonts
 BuildRequires:  dbus-x11
 %endif # with_check
 
+Patch0: 0001-IntrospectionModule-handle-two-threads-loading-type-.patch
+
 %description
 The %{name} package provides a convenient wrapper for the GObject library
 for use in Python programs.
@@ -72,6 +74,7 @@ This package contains files required to embed PyGObject
 
 %prep
 %setup -q -n pygobject-%{version}
+%patch0 -p1 -b .lockablock
 
 find -name '*.py' | xargs sed -i '1s|^#!python|#!%{__python3}|'
 
@@ -126,6 +129,11 @@ xvfb-run make DESTDIR=$RPM_BUILD_ROOT check V=1
 %{_libdir}/pkgconfig/pygobject-3.0.pc
 
 %changelog
+* Thu Jun 11 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-2
+- Add lock to avoid two type object wrappers getting generated at
+  the same time in multi-threaded programs.
+  Resolves: #1844578
+
 * Fri Aug 10 2018 Kalev Lember <klember@redhat.com> - 3.28.3-1
 - Update to 3.28.3