Repository: DataDog/dd-trace-py

Issue:
Intermittent `RuntimeError: the memalloc module was not started` error
### Which version of dd-trace-py are you using?

`ddtrace==0.57.0`

### What is the result that you get?

`RuntimeError: the memalloc module was not started`

![148817478-801fc910-af78-4f45-a06c-b77e8924aeb7](https://user-images.githubusercontent.com/49695/148818367-e625ecfa-80a5-4c24-b08b-0cc29448dec4.png)

### What is the result that you expected?

No errors.

This seems to be happening a few times a day.

We have tried setting `DD_PROFILING_HEAP_ENABLED=False` and `DD_PROFILING_MEMALLOC=0` in the environment, but the errors continue to appear.


Configuration in Django:
```
import os
from ddtrace import config, tracer

# DataDog Setup
tracer.configure(hostname=os.environ.get("HOST_IP"))
tracer.configure(enabled=True)
tracer.set_tags(
    {"env": os.environ.get("ENVIRONMENT"), "namespace": os.environ.get("NAMESPACE")}
)
config.django["analytics_enabled"] = True
config.django["cache_service_name"] = "xxx-cache"
config.django["database_service_name_prefix"] = "xxx"
config.django["distributed_tracing_enabled"] = True
config.django["instrument_middleware"] = True
config.django["service_name"] = "xxx"

```



Discussion:
We are facing the same issue (same `ddtrace` version) with a Fastapi app. I'd be happy to share logs/config you need.
Could you share:
1. which Web server you're running?
2. Its configuration?
3. If you're using gevent?
I am using nginx feeding into gunicon/gevent with regular proxy setup. Not sure which configurations would be helpful to you?
We have 2 different servers (not behind nginx).

**flask**
1. Gunicorn
2. `--worker-class=gthread`
3. No

**fastapi**
1. Gunicorn
2. `--worker-class=uvicorn.workers.UvicornWorker`
3. No
+1 We have the same issue with Gunicorn + Django
+1 same in `0.59.1` we are using sanic with profiling enabled: `DD_PROFILING_ENABLED=true`

```
datadog~=0.44.0
ddtrace~=0.59.1
requests~=2.27.1
sanic~=19.12.2
```

<img width="1343" alt="image" src="https://user-images.githubusercontent.com/19598277/159076397-a20fc9dc-4f0b-4332-a4c0-0dba795b8b6b.png">

Currently, having the same issue 
Same issue, with Flask/gunicorn/gevent, using ddtrace 1.2.1:
```

RuntimeError: the memalloc module was not started
  File "ddtrace/internal/periodic.py", line 70, in run
    self._target()
  File "ddtrace/profiling/collector/__init__.py", line 42, in periodic
    for events in self.collect():
  File "ddtrace/profiling/collector/memalloc.py", line 145, in collect
    events, count, alloc_count = _memalloc.iter_events()
```


Same issue with Flask/gunicorn/gevent as well using ddtrace 1.4.4:
<img width="766" alt="image" src="https://user-images.githubusercontent.com/3894011/201698121-ef82b8fb-f191-4a7b-9a8f-2841c37e57bf.png">

This might be due to gevent monkey patching not done properly.
Is everyone using `DD_GEVENT_PATCH_ALL=1`?
@jd we're working on adding `DD_GEVENT_PATCH_ALL` in as recommended by Datadog support. we also need to upgrade some other some deps along the way to make it work. i'll post back if that gets us resolved.
@rgilkey did adding `DD_GEVENT_PATCH_ALL` resolve the issue? I'm facing the same problem with ddtrace v1.7.5
We are currently facing the same issue, and it seems to be a bit random, it appears really punctually...
We use Flask + Gunicorn and ddtrace==1.0.1

Resolving patch:
diff --git a/ddtrace/profiling/collector/memalloc.py b/ddtrace/profiling/collector/memalloc.py
--- a/ddtrace/profiling/collector/memalloc.py
+++ b/ddtrace/profiling/collector/memalloc.py
@@ -148,7 +148,13 @@ def snapshot(self):
         )
 
     def collect(self):
-        events, count, alloc_count = _memalloc.iter_events()
+        try:
+            events, count, alloc_count = _memalloc.iter_events()
+        except RuntimeError:
+            # DEV: This can happen if either _memalloc has not been started or has been stopped.
+            LOG.debug("Unable to collect memory events from process %d", os.getpid(), exc_info=True)
+            return tuple()
+
         capture_pct = 100 * count / alloc_count
         thread_id_ignore_set = self._get_thread_id_ignore_set()
         # TODO: The event timestamp is slightly off since it's going to be the time we copy the data from the


Test patch: