<p dir="auto">I'm using python 2.7 on numpy 1.10.1 with a custom dtype implementation.  Essentially the self-&gt;userloops is defined with types that do not match the specified_types.  In such case numpy will hang indefinitely.</p>
<p dir="auto">It seems like the function  type_tuple_userloop_type_resolver in numpy/numpy/core/src/umath/ufunc_type_resolution.c is incorrect.  It can get into an infinite loop  around line 1745, which looks like:</p>
<div class="highlight highlight-source-c notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="            while (funcdata != NULL) {
                int *types = funcdata-&gt;arg_types;
                int matched = 1;

                if (n_specified == nop) {
                    for (j = 0; j &lt; nop; ++j) {
                        if (types[j] != specified_types[j] &amp;&amp;
                                    specified_types[j] != NPY_NOTYPE) {
                            matched = 0;
                            break;
                        }
                    }
                } else {
                    if (types[nin] != specified_types[0]) {
                        matched = 0;
                    }
                }
                if (!matched) {
                    continue;
                }

                switch (ufunc_loop_matches(self, op,
                            casting, casting,
                            any_object, use_min_scalar,
                            types, NULL,
                            &amp;no_castable_output, &amp;err_src_typecode,
                            &amp;err_dst_typecode)) {
                    /* It works */
                    case 1:
                        set_ufunc_loop_data_types(self, op,
                            out_dtype, types, NULL);
                        return 1;
                    /* Didn't match */
                    case 0:
                        PyErr_Format(PyExc_TypeError,
                             &quot;found a user loop for ufunc '%s' &quot;
                             &quot;matching the type-tuple, &quot;
                             &quot;but the inputs and/or outputs could not be &quot;
                             &quot;cast according to the casting rule&quot;,
                             self-&gt;name ? self-&gt;name : &quot;(unknown)&quot;);
                        return -1;
                    /* Error */
                    case -1:
                        return -1;
                }

                funcdata = funcdata-&gt;next;
            }"><pre class="notranslate">            <span class="pl-k">while</span> (<span class="pl-s1">funcdata</span> <span class="pl-c1">!=</span> <span class="pl-c1">NULL</span>) {
                <span class="pl-smi">int</span> <span class="pl-c1">*</span><span class="pl-s1">types</span> <span class="pl-c1">=</span> <span class="pl-s1">funcdata</span><span class="pl-c1">-&gt;</span><span class="pl-c1">arg_types</span>;
                <span class="pl-smi">int</span> <span class="pl-s1">matched</span> <span class="pl-c1">=</span> <span class="pl-c1">1</span>;

                <span class="pl-k">if</span> (<span class="pl-s1">n_specified</span> <span class="pl-c1">==</span> <span class="pl-s1">nop</span>) {
                    <span class="pl-k">for</span> (<span class="pl-s1">j</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span>; <span class="pl-s1">j</span> <span class="pl-c1">&lt;</span> <span class="pl-s1">nop</span>; <span class="pl-c1">++</span><span class="pl-s1">j</span>) {
                        <span class="pl-k">if</span> (<span class="pl-s1">types</span>[<span class="pl-s1">j</span>] <span class="pl-c1">!=</span> <span class="pl-s1">specified_types</span>[<span class="pl-s1">j</span>] <span class="pl-c1">&amp;&amp;</span>
                                    <span class="pl-s1">specified_types</span>[<span class="pl-s1">j</span>] <span class="pl-c1">!=</span> <span class="pl-c1">NPY_NOTYPE</span>) {
                            <span class="pl-s1">matched</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span>;
                            <span class="pl-k">break</span>;
                        }
                    }
                } <span class="pl-k">else</span> {
                    <span class="pl-k">if</span> (<span class="pl-s1">types</span>[<span class="pl-s1">nin</span>] <span class="pl-c1">!=</span> <span class="pl-s1">specified_types</span>[<span class="pl-c1">0</span>]) {
                        <span class="pl-s1">matched</span> <span class="pl-c1">=</span> <span class="pl-c1">0</span>;
                    }
                }
                <span class="pl-k">if</span> (!<span class="pl-s1">matched</span>) {
                    <span class="pl-k">continue</span>;
                }

                <span class="pl-k">switch</span> (<span class="pl-en">ufunc_loop_matches</span>(<span class="pl-s1">self</span>, <span class="pl-s1">op</span>,
                            <span class="pl-s1">casting</span>, <span class="pl-s1">casting</span>,
                            <span class="pl-s1">any_object</span>, <span class="pl-s1">use_min_scalar</span>,
                            <span class="pl-s1">types</span>, <span class="pl-c1">NULL</span>,
                            <span class="pl-c1">&amp;</span><span class="pl-s1">no_castable_output</span>, <span class="pl-c1">&amp;</span><span class="pl-s1">err_src_typecode</span>,
                            <span class="pl-c1">&amp;</span><span class="pl-s1">err_dst_typecode</span>)) {
                    <span class="pl-c">/* It works */</span>
                    <span class="pl-k">case</span> <span class="pl-c1">1</span>:
                        <span class="pl-en">set_ufunc_loop_data_types</span>(<span class="pl-s1">self</span>, <span class="pl-s1">op</span>,
                            <span class="pl-s1">out_dtype</span>, <span class="pl-s1">types</span>, <span class="pl-c1">NULL</span>);
                        <span class="pl-k">return</span> <span class="pl-c1">1</span>;
                    <span class="pl-c">/* Didn't match */</span>
                    <span class="pl-k">case</span> <span class="pl-c1">0</span>:
                        <span class="pl-en">PyErr_Format</span>(<span class="pl-s1">PyExc_TypeError</span>,
                             <span class="pl-s">"found a user loop for ufunc '%s' "</span>
                             <span class="pl-s">"matching the type-tuple, "</span>
                             <span class="pl-s">"but the inputs and/or outputs could not be "</span>
                             <span class="pl-s">"cast according to the casting rule"</span>,
                             <span class="pl-s1">self</span><span class="pl-c1">-&gt;</span><span class="pl-c1">name</span> ? <span class="pl-s1">self</span><span class="pl-c1">-&gt;</span><span class="pl-c1">name</span> : <span class="pl-s">"(unknown)"</span>);
                        <span class="pl-k">return</span> <span class="pl-c1">-1</span>;
                    <span class="pl-c">/* Error */</span>
                    <span class="pl-k">case</span> <span class="pl-c1">-1</span>:
                        <span class="pl-k">return</span> <span class="pl-c1">-1</span>;
                }

                <span class="pl-s1">funcdata</span> <span class="pl-c1">=</span> <span class="pl-s1">funcdata</span><span class="pl-c1">-&gt;</span><span class="pl-c1">next</span>;
            }</pre></div>
<p dir="auto">I see that if matched = 0, then the loop does a "continue" without updating the funcdata.  Thus funcdata is never null and will run forever.</p>
<p dir="auto">In relation to <a href="https://github.com/moble/quaternion/issues/54" data-hovercard-type="issue" data-hovercard-url="/moble/quaternion/issues/54/hovercard">a bug filed on my numpy quaternion package</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/eric-wieser/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/eric-wieser">@eric-wieser</a> found a bug in numpy.  He reports an infinite loop in <code class="notranslate">type_tuple_userloop_type_resolver</code>.  I don't actually understand that code, but I guess he's talking about the <code class="notranslate">continue</code> statement in <a href="https://github.com/numpy/numpy/blob/master/numpy/core/src/umath/ufunc_type_resolution.c#L1796">this loop</a> short-circuiting the <code class="notranslate">funcdata = funcdata-&gt;next</code> statement, which means the loop condition doesn't change between iterations.</p>
<p dir="auto">Presumably, that bug needs to be fixed regardless, but (not really understanding numpy's internals) I wonder if I could have also done something in the quaternion package to avoid this problem.  My package attempts to add a new dtype to numpy, so maybe it also needs to update some internal list of dtypes that numpy maintains???  If so, I welcome comments.</p>